用PyTorch实现Logistic回归

目录

1、数据准备

2、线性方程

3、激活函数、损失函数

4、利用nn.Module来实现Logistic回归

1、数据准备

#导包
import torch
from torch import nn
import matplotlib.pyplot as plt
# %matplotlib inline
import numpy as np
from torch.distributions import MultivariateNormal
# 设置两组不同的均值向量和协方差矩阵
# torch.eye()主要是为了生成对角线全是1,其余部分全0的二维数组
mu1 = -3 * torch.ones(2)
mu2 = 3 * torch.ones(2)
sigma1 = torch.eye(2) * 0.5
sigma2 = torch.eye(2) * 2
# 各从两个多元高斯分布中生成100个样本
# 此处定义的多元高斯是二维的
m1 = MultivariateNormal(mu1, sigma1)
m2 = MultivariateNormal(mu2, sigma2)
x1 = m1.sample((100,))
x2 = m2.sample((100,))

#设置正负样本的标签
y = torch.zeros((200, 1))
y[100:] = 1

# 组合、打乱样本
x = torch.cat([x1, x2], dim=0)
# np.random.permutation():1、产生一个随机序列 2、对一个随机序列x进行随机排序 3、如果x是一个多维数组,它只会按照第一个索引洗牌
idx = np.random.permutation(len(x))
x = x[idx]
y = y[idx]

# # 绘制样本
plt.scatter(x1.numpy()[:,0], x1.numpy()[:,1])
plt.scatter(x2.numpy()[:,0], x2.numpy()[:,1])
plt.show()

结果:

从图中可以看出右上角的簇样本分布稀疏,而左下角分布紧凑。可以自行调整9-10行代码的参数,观察其变化。

2、线性方程

# 线性方程
# D_in为输入的特征数,D_out为输出的特征数
D_in, D_out = 2, 1
linear = nn.Linear(D_in, D_out, bias=True)
output = linear(x)

print(x.shape, linear.weight.shape, linear.bias.shape, output.shape)

def my_linear(x, w, b):
    return torch.mm(x, w.t()) + b

torch.sum((output - my_linear(x, linear.weight, linear.bias)))

3、激活函数、损失函数

# 激活函数
sigmoid = nn.Sigmoid()
scores = sigmoid(output)

def my_sigmoid(x):
    x = 1/(1 + torch.exp(-x))
    return x

# 通过PyTorch验证我们的试验结果
torch.sum(scores - my_sigmoid(output))

# 损失函数
# Logistic回归使用交叉熵作为损失函数
loss = nn.BCELoss()
loss(scores, y)

# 下面自定义了二值交叉熵函数,将my_loss和PyTorch的BCELoss进行比较
def my_loss(x, y):
    loss = - torch.mean(torch.log(x) * y + torch.log(1 - x) * (1 - y))
    return loss

loss(scores, y) - my_loss(my_sigmoid(output), y)

4、利用nn.Module来实现Logistic回归

以上是我们使用的torch.nn包中的线性模型nn.Linear、激活函数,损失函数,它们都继承自nn.Module类。而在PyTorch中,我们继承nn.Module来构建我们自己的模型。接下来我们用nn.Module来实现Logistic回归。
import torch.nn as nn

class LogisticRegression(nn.Module):
    def __init__(self, D_in):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(D_in, 1)
        self.sigmoid = nn.Sigmoid()

    # forward方法是必须被子类覆写的,在forward内部应当定义每次调用模型时执行的计算
    def forward(self, x):
        x = self.linear(x)
        x = self.sigmoid(x)
        return x
#nn.Module类的主要作用就是接收Tensor然后计算并返回结果
lr_model = LogisticRegression(2)
loss = nn.BCELoss()
# print(loss(lr_model(x), y))

# 优化算法
'''
Logistic回归通常采用梯度下降法优化目标函数。
PyTorch的torch.optim包实现了大多数常用算法
'''
from torch import optim

optimizer = optim.SGD(lr_model.parameters(), lr=0.03)
'''
构建完优化器,就可以迭代地对模型进行训练,有两个步骤:
1、调用损失函数的backward方法计算模型的梯度
2、调用优化器的step方法更新模型的参数
需要注意的是,应当提前调用优化器zero_grad方法清空参数的梯度
'''

batch_size = 10
iters = 10
# for input, target in dataset:
for _ in range(iters):
    for i in range(int(len(x)/batch_size)):
        input = x[i*batch_size:(i+1)*batch_size]
        target = y[i*batch_size:(i+1)*batch_size]
        optimizer.zero_grad()
        output = lr_model(input)
        l = loss(output, target)
        l.backward()
        optimizer.step()

# 优化算法
'''
Logistic回归模型的判决边界在高维空间的一个超平面,而我们的数据集是二维,所以判决边界只是平面内的一条直线,
在线的一侧被预测为正类,另一侧则被预测为父类。
draw_decision_boundary函数接收线性模型的参数w和b,以及数据集x。
绘制判决边界只需要计算一些数据在线模型的映射值,然后调用plt.plot绘制线条即可。
'''

pred_neg = (output <= 0.5).view(-1)
pred_pos = (output > 0.5).view(-1)
plt.scatter(x[pred_neg, 0], x[pred_neg, 1])
plt.scatter(x[pred_neg, 0], x[pred_pos, 1])

w = lr_model.linear.weight[0]
b = lr_model.linear.bias[0]

def draw_decision_boundary(w, b, x0):
    x1 = (-b - w[0] * x0) / w[1]
    plt.plot(x0.detach().numpy(), x1.detach().numpy(), 'r')
    plt.show()

draw_decision_boundary(w, b, torch.linspace(x.min(), x.max(), 50))


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值