Pytorch入门教程06-损失函数和优化器

王 茂南 2020年10月5日07:13:20
评论
2 2159字阅读7分11秒
摘要在之前的内容中, 我们通过自己定义的损失函数和系数更新的方法来更新系数. 但其实在Pytorch中, 已经包含了相应的函数, 可以直接来计算损失, 和完成梯度下降. 所以在这一部分, 我们会介绍优化器和损失函数.

简介

在上一篇文章中, 我们介绍了梯度下降算法, 在求出系数的偏导之后, 如何来进行系数的优化. 但是在上一次文章中, 我们自己定义了损失函数和系数更新的方法.

但其实在 Pytorch 中, 包含了相应的函数, 可以直接来计算损失, 和完成梯度下降. 所以在这一篇中, 我们还是使用求解一元线性回归的例子, 来看一下如何使用 Pytorch 默认提供的函数求解. 同时, 我们会来看一下如何动态调整优化器的学习率, 即动态调整 learning rate.

Github仓库链接: 损失函数和优化器的介绍

 

损失函数与优化器

定义模型

我们首先定义我们需要用到的线性模型, 这里只需要一个参数 w.

  1. w = torch.tensor(0.0, dtype=torch.float32, requires_grad=True)
  2. def forward(x):
  3.     return w * x

 

损失函数

在线性回归的例子中, 我们应该使用均方差损失函数, 使用 torch.nn.MSELoss() 表示. 于是我们可以将代码写成下面的形式.

  1. loss = torch.nn.MSELoss() # 定义均方损失函数

 

优化器

之前我们使用了最基础的梯度下降来更新参数w. 但其实, 在torch.optim中存在着各种梯度下降的改进算法, 比如 SGD, Momentum, RMSProp 和 Adam 等. (这些算法都是以传统梯度下降算法为基础改进得到的, 这些算法可以更快更准确地求解最佳模型参数.)

我们在这里定义一个 SGD 优化器,

  1. optimizer = torch.optim.SGD([w], lr=learning_rate)

其中:

  • w 表示我们要更新的参数(网络的权重)
  • lr 表示学习率

在 Pytorch 中, 还 optimizer 还提供可以一次更新全部的参数, 和参数梯度清零两个功能.

  • optimizer.step(): 对神经网络(复合函数)的相关变量进行更新, 即所有参数值向梯度相反方向走一步;
  • optimizer.zero_grad(): 对神经网络(复合函数)的相关系数进行梯度的清空;

我们还可以在优化器中加入 weight decay 的内容. 在 Pytorch 中, 默认的是 L2 的正则项. 我们可以使用下面的方法来实现. 下面是只对 weight 进行正则化, 不对 bias 进行正则化.

  1. trainer = torch.optim.SGD([{"params":net[0].weight,'weight_decay': wd},{"params":net[0].bias}], lr=lr)

 

更新权重

有了上面定义的损失函数和优化器之后, 我们就可以开始更新权重 w 了.

  1. X_tensor = torch.from_numpy(X)
  2. Y_tensor = torch.from_numpy(Y)
  3. n_iters = 100
  4. for epoch in range(n_iters):
  5.     y_pred = forward(X_tensor)
  6.     l = loss(Y_tensor, y_pred) # 求误差(注意这里的顺序)
  7.     l.backward() # 求梯度
  8.     optimizer.step()  # 更新权重,即向梯度方向走一步
  9.     optimizer.zero_grad() # 清空梯度
  10.     if epoch % 20 == 0:
  11.         print(f'epoch {epoch+1}: w = {w.item():.3f}, loss = {l.item():.3f}')
  12. print(f'根据训练模型预测, 当x=5时, y的值为: {forward(5):.3f}')
  13. """
  14. epoch 1: w = 0.142, loss = 153.912
  15. epoch 21: w = 1.642, loss = 10.674
  16. epoch 41: w = 2.028, loss = 1.210
  17. epoch 61: w = 2.127, loss = 0.585
  18. epoch 81: w = 2.152, loss = 0.544
  19. 根据训练模型预测, 当x=5时, y的值为: 10.794
  20. """

可以看到在经过100次迭代之后, 最终的系数 w 接近于 2.

 

调整优化器的学习率

在训练的过程中,我们通常需要动态的对优化器(optimizer)的学习率进行调整。下面介绍如何动态的调整优化器的学习率。

直接通过 optimizer.param_groups 调整

当我们定义好了一个 optimizer 之后,我们可以通过 optimizer.param_groups 来进行调整。下面看一个简单的例子,每 30 个 epoch 会对 lr 降低 10%。

  1. def adjust_learning_rate(optimizer, epoch, init_lr):
  2.     """Sets the learning rate to the initial LR decayed by 10 every 30 epochs
  3.     """
  4.     lr = init_lr * (0.1 ** (epoch // 30))
  5.     for param_group in optimizer.param_groups:
  6.         param_group['lr'] = lr

 

  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南
  • 本文由 发表于 2020年10月5日07:13:20
  • 转载请务必保留本文链接:https://mathpretty.com/12514.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: