0 写在前面
Task2 的内容是苹果书的 3.3-自适应学习率,3.4-学习率调度,3.5-优化总结,3.6-分类,HW3 CNN 图像分类实践任务。3.3到3.5节在前面的动量基础上补充了自适应学习率和学习率调度的内容,3.6节则讲解了分类任务的定义以及相关的损失函数。Task 2 内容的思维导图如下所示:
1 自适应学习率
1.1 为什么需要自适应学习率
在训练网络的过程中,常常会遇到 loss 无法继续下降的情况,但这个时候不一定是到了鞍点或者局部极小值点,通常是因为普通的梯度下降无法继续让 loss 进一步下降了。在普通的梯度下降中,设置过大的学习率时,容易导致梯度在“山谷”的两边震荡;设置过小的学习率时,容易导致梯度在较为“平坦”的误差表面难以“前进”。这个时候就需要为每个参数定制学习率,也就是自适应学习率。
1.2 自适应学习率的核心思想
用一句话来总结就是:大坡度(大梯度),走小步(学习率小);小坡度(小梯度),走大步(学习率大)。
1.3 常用技术
首先我们在这里写出最原始的梯度下降的公式:
其中:
1.3.1 Adagrad
在 Adagrad 中,梯度更新的公式变为:
其中:
本质上是考虑了前面所有的梯度,但这里的“考虑”与动量中也有所不同,这里计算了前面梯度的 RMS 。
1.3.2 RMSProp
与AdaGrad中使用的RMS相比,RMSProp让我们可以对现在梯度与以前梯度的重要性进行调整:
1.3.3 Adam
Adam 的本质简单来说就是 RMSProp 与动量的结合。
2 学习率调度
2.1 为什么需要学习率调度
如图所示,在红色圈内,y轴发生了梯度突然开始震荡的情况。这是因为在使用自适应梯度下降后,由A到B,再由B到C的过程中,绿色方框内的这段y轴上的梯度很小,误差表面较为平坦,而 是一个累积的结果,这就导致了 会逐渐变成一个很小的值,学习率逐渐变大,然后就引起了梯度震荡。但是这种震荡不是持续的,因为震荡到梯度较大的地方后, 又会逐渐变大,从而使得学习率逐渐变小,进而回到正轨。为了能让梯度直接从B到C而不产生震荡,我们需要采用学习率调度。
2.2 常用的学习率调度
2.2.1 learning rate decay
随着训练的进行,我们距离终点越近,一般来说所需要迈的步子越小,所以学习率持续减小。
2.2.2 warm up
warm up 则是先从一个小的学习率开始,逐渐增加学习率。
3 优化总结
优化从最原始的梯度下降:
在增加了动量,自适应学习率以及学习率调度后,变为以下的常用形式:
在不同的优化方法中,一般就是对动量 ,自适应学习率 ,以及学习率调度策略 进行修改。
4 分类
由于分类部分的内容较为基础,书中也写得很详细,所以这里就不过多赘述,有需要的读者可以直接查看书中的内容
5 HW3 CNN 图像分类实践
下面是通过修改部分设置,例如调整学习率,使用其他优化器等,得到的不同 t-SNE 实验结果
5.1 sample
5.2 调整学习率
将学习率调整为 0.03,可以看出来效果差了很多。
5.3 学习率调度
在这里我随机选用了一个学习率调度机制,StepLR,每达到一定epoch数量后,将学习率乘以一个固定的因子。具体的代码可以参考下面:
from torch.optim.lr_scheduler import StepLR
# 定义 optimizer
optimizer = optim.Adam(model.parameters(), lr=0.01)
# 定义 scheduler
scheduler = StepLR(optimizer, step_size=2, gamma=0.1) # 每两轮就乘 0.1
然后记得再 train loop 中加入:
# 更新学习率
scheduler.step()