PyTorch使用教程-PyTorch构建神经网络(上)
前言
我们已经了解到了Pytorch的基本用法,以及自动求导的使用,有了这些预备知识我们已经可以做一个最简单的逻辑回归模型了
准备
最简单的回归模型莫过于二元一次模型了
y = w * x + b
自定义准备w
和b
,我们要做的就是学习样本数据,然后反推出w
和b
的值,但是不一定是最准确的,但我们要尽可能找到最优的
输入,使用均匀分布的100个0-1的随机数
x = torch.rand(100, 1)
输出,由于我们模拟真实环境,因此偏置上我们再随机的产生噪声让他去影响原数据
real_out = w * x + b + torch.rand(100,1)
画出样本数据的分布
plt.scatter(x.numpy(), real_out.numpy())
plt.show()
注
:我设置的w
和b
分别是10
和8.8
初始化训练程序
初始化w
和b
w = torch.tensor(0.)
w.requires_grad_(True)
b = torch.tensor(0.)
b.requires_grad_(True)
lr = torch.tensor(0.001)
注释
:由于我们需要对w
和b
求导,因此需要设置requires_grad
为True
训练主程序
for i in range(100000):
pre_out = w * x + b
loss = ((pre_out-real_out)**2).mean()
loss.backward()
w.data = w.data - lr*w.grad.data
b.data = b.data - lr*b.grad.data
w.grad.data = torch.tensor(0.)
b.grad.data = torch.tensor(0.)
if (i+1) % 10000==0:
print(loss)
注释
:backward
后自动将grad
累积到requires_grad
为True
的对应tensor
的grad
上,因此每算一步梯度更新参数后,都需要将累计的梯度清零,读者可以试试不清零会发生什么对应代码
w.grad.data = torch.tensor(0.)
b.grad.data = torch.tensor(0.)
由于梯度计算出来的方向是,指向越来越大的方向的,因此需要加上负号
对应代码
w.data = w.data - lr*w.grad.data
b.data = b.data - lr*b.grad.data
其中lr
是非常重要的超参数,意义是学习率
- 学习率
小
时间足够长那么我们的模型可以到达一个局部最优值,能收敛 - 学习率
过大
就会导致模型来回振荡而无法收敛
训练结果
print('pre_w:{} pre_b:{}'.format(w.detach().numpy(), b.detach().numpy()))
pre_out = w * x + b
plt.plot(x.detach().numpy(), pre_out.detach().numpy(), c='r')
plt.scatter(x.detach().numpy(), real_out.detach().numpy(), c='b')
plt.show()
原w=10
和b=8.8
pre_w:9.886486053466797 pre_b:9.393828392028809
蓝色圆点是原数据,红色直线为预测直线,效果还不错
总结
本节使用了上节学到的backward
就实现了一个简单的线性回归
模型,优化器或梯度清零虽然有高层的api封装,但是我们也必须了解其原理才能更加深刻的理解梯度下降
,帮助我们后面进行DIY