文章目录(Table of Contents)
简介
在上一篇文章中, 我们介绍了梯度下降算法, 在求出系数的偏导之后, 如何来进行系数的优化. 但是在上一次文章中, 我们自己定义了损失函数和系数更新的方法.
但其实在 Pytorch 中, 包含了相应的函数, 可以直接来计算损失, 和完成梯度下降. 所以在这一篇中, 我们还是使用求解一元线性回归的例子, 来看一下如何使用 Pytorch 默认提供的函数求解. 同时, 我们会来看一下如何动态调整优化器的学习率, 即动态调整 learning rate.
Github仓库链接: 损失函数和优化器的介绍
损失函数与优化器
定义模型
我们首先定义我们需要用到的线性模型, 这里只需要一个参数 w.
- w = torch.tensor(0.0, dtype=torch.float32, requires_grad=True)
- def forward(x):
- return w * x
损失函数
在线性回归的例子中, 我们应该使用均方差损失函数, 使用 torch.nn.MSELoss()
表示. 于是我们可以将代码写成下面的形式.
- loss = torch.nn.MSELoss() # 定义均方损失函数
优化器
之前我们使用了最基础的梯度下降来更新参数w. 但其实, 在torch.optim
中存在着各种梯度下降的改进算法, 比如 SGD, Momentum, RMSProp 和 Adam 等. (这些算法都是以传统梯度下降算法为基础改进得到的, 这些算法可以更快更准确地求解最佳模型参数.)
我们在这里定义一个 SGD 优化器,
- optimizer = torch.optim.SGD([w], lr=learning_rate)
其中:
- w 表示我们要更新的参数(网络的权重)
- lr 表示学习率
在 Pytorch 中, 还 optimizer 还提供可以一次更新全部的参数, 和参数梯度清零两个功能.
optimizer.step()
: 对神经网络(复合函数)的相关变量进行更新, 即所有参数值向梯度相反方向走一步;optimizer.zero_grad()
: 对神经网络(复合函数)的相关系数进行梯度的清空;
我们还可以在优化器中加入 weight decay 的内容. 在 Pytorch 中, 默认的是 L2 的正则项. 我们可以使用下面的方法来实现. 下面是只对 weight 进行正则化, 不对 bias 进行正则化.
- trainer = torch.optim.SGD([{"params":net[0].weight,'weight_decay': wd},{"params":net[0].bias}], lr=lr)
更新权重
有了上面定义的损失函数和优化器之后, 我们就可以开始更新权重 w 了.
- X_tensor = torch.from_numpy(X)
- Y_tensor = torch.from_numpy(Y)
- n_iters = 100
- for epoch in range(n_iters):
- y_pred = forward(X_tensor)
- l = loss(Y_tensor, y_pred) # 求误差(注意这里的顺序)
- l.backward() # 求梯度
- optimizer.step() # 更新权重,即向梯度方向走一步
- optimizer.zero_grad() # 清空梯度
- if epoch % 20 == 0:
- print(f'epoch {epoch+1}: w = {w.item():.3f}, loss = {l.item():.3f}')
- print(f'根据训练模型预测, 当x=5时, y的值为: {forward(5):.3f}')
- """
- epoch 1: w = 0.142, loss = 153.912
- epoch 21: w = 1.642, loss = 10.674
- epoch 41: w = 2.028, loss = 1.210
- epoch 61: w = 2.127, loss = 0.585
- epoch 81: w = 2.152, loss = 0.544
- 根据训练模型预测, 当x=5时, y的值为: 10.794
- """
可以看到在经过100次迭代之后, 最终的系数 w 接近于 2.
调整优化器的学习率
在训练的过程中,我们通常需要动态的对优化器(optimizer)的学习率进行调整。下面介绍如何动态的调整优化器的学习率。
直接通过 optimizer.param_groups 调整
当我们定义好了一个 optimizer 之后,我们可以通过 optimizer.param_groups 来进行调整。下面看一个简单的例子,每 30 个 epoch 会对 lr 降低 10%。
- def adjust_learning_rate(optimizer, epoch, init_lr):
- """Sets the learning rate to the initial LR decayed by 10 every 30 epochs
- """
- lr = init_lr * (0.1 ** (epoch // 30))
- for param_group in optimizer.param_groups:
- param_group['lr'] = lr
- 微信公众号
- 关注微信公众号
- QQ群
- 我们的QQ群号
评论