Datawhale X 李宏毅苹果书Al夏令营——Task2

92 阅读4分钟

0 写在前面

Task2 的内容是苹果书的 3.3-自适应学习率,3.4-学习率调度,3.5-优化总结,3.6-分类,HW3 CNN 图像分类实践任务。3.3到3.5节在前面的动量基础上补充了自适应学习率和学习率调度的内容,3.6节则讲解了分类任务的定义以及相关的损失函数。Task 2 内容的思维导图如下所示:

image.png

1 自适应学习率

1.1 为什么需要自适应学习率

在训练网络的过程中,常常会遇到 loss 无法继续下降的情况,但这个时候不一定是到了鞍点或者局部极小值点,通常是因为普通的梯度下降无法继续让 loss 进一步下降了。在普通的梯度下降中,设置过大的学习率时,容易导致梯度在“山谷”的两边震荡;设置过小的学习率时,容易导致梯度在较为“平坦”的误差表面难以“前进”。这个时候就需要为每个参数定制学习率,也就是自适应学习率。

1.2 自适应学习率的核心思想

用一句话来总结就是:大坡度(大梯度),走小步(学习率小);小坡度(小梯度),走大步(学习率大)。

1.3 常用技术

首先我们在这里写出最原始的梯度下降的公式:

θit+1=θitηgit\bm{\theta}_i^{t+1} = \bm{\theta}_i^{t}-\eta\bm{g}_i^{t}

其中:

git=Lθiθ=θt\bm{g}_i^{t} = \left.\frac{\partial L}{\partial \bm{\theta}_i}\right|_{\bm{\theta}=\bm{\theta}_t}

1.3.1 Adagrad

在 Adagrad 中,梯度更新的公式变为:

θit+1=θitησitgit\bm{\theta}_i^{t+1} = \bm{\theta}_i^{t}-\frac{\eta}{\sigma_i^t}\bm{g}_i^{t}

其中:

σit=1t+1j=0t(gij)2\sigma_i^t=\sqrt{\frac{1}{t+1}\sum_{j=0}^t(\bm{g}_i^j)^2}

本质上是考虑了前面所有的梯度,但这里的“考虑”与动量中也有所不同,这里计算了前面梯度的 RMS 。

1.3.2 RMSProp

与AdaGrad中使用的RMS相比,RMSProp让我们可以对现在梯度与以前梯度的重要性进行调整:

σit=α(σit1)2+(1α)(git)2 \sigma_i^t=\sqrt{\alpha(\sigma_i^{t-1})^2+(1-\alpha)(\bm{g}_i^t)^2}

1.3.3 Adam

Adam 的本质简单来说就是 RMSProp 与动量的结合。

2 学习率调度

2.1 为什么需要学习率调度

image.png

如图所示,在红色圈内,y轴发生了梯度突然开始震荡的情况。这是因为在使用自适应梯度下降后,由A到B,再由B到C的过程中,绿色方框内的这段y轴上的梯度很小,误差表面较为平坦,而 σit\sigma_i^{t} 是一个累积的结果,这就导致了 σit\sigma_i^{t} 会逐渐变成一个很小的值,学习率逐渐变大,然后就引起了梯度震荡。但是这种震荡不是持续的,因为震荡到梯度较大的地方后,σit\sigma_i^{t} 又会逐渐变大,从而使得学习率逐渐变小,进而回到正轨。为了能让梯度直接从B到C而不产生震荡,我们需要采用学习率调度。

2.2 常用的学习率调度

2.2.1 learning rate decay

image.png

随着训练的进行,我们距离终点越近,一般来说所需要迈的步子越小,所以学习率持续减小。

2.2.2 warm up

image.png

warm up 则是先从一个小的学习率开始,逐渐增加学习率。

3 优化总结

优化从最原始的梯度下降:

θit+1=θitηgit\bm{\theta}_i^{t+1} = \bm{\theta}_i^{t}-\eta\bm{g}_i^{t}

在增加了动量,自适应学习率以及学习率调度后,变为以下的常用形式:

θit+1=θitηtσitmit\bm{\theta}_i^{t+1} = \bm{\theta}_i^{t}-\frac{\eta^t}{\sigma_i^t}m_i^t

在不同的优化方法中,一般就是对动量 mitm_i^t,自适应学习率 σit\sigma_i^t,以及学习率调度策略 ηt\eta^t 进行修改。

4 分类

由于分类部分的内容较为基础,书中也写得很详细,所以这里就不过多赘述,有需要的读者可以直接查看书中的内容

5 HW3 CNN 图像分类实践

下面是通过修改部分设置,例如调整学习率,使用其他优化器等,得到的不同 t-SNE 实验结果

5.1 sample

sample.png

5.2 调整学习率

将学习率调整为 0.03,可以看出来效果差了很多。

调整学习率.png

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()

学习率调度.png

5.4 Adagrad

Adagrad.png

5.5 RMSProp

RMSProp.png

参考资料

  1. 李宏毅深度学习教程