Gradient Descent 梯度下降 II
关于 Gradient Descent 的直观解释,参考上一篇博客【机器学习】梯度下降 I
本模块介绍几种梯度下降模型。定义符号标记如下:
- \(\theta_t\):第 t 步的参数
- \(\nabla L(\theta_t)\) or \(g_t\):\(\theta_t\)的梯度
- \(m_{t+1}\):从 0 时刻开始累积的动量
SGD
\(\theta_{t+1} = \theta_t - \eta\nabla L(\theta_t)\)
-
特点:最简单、比较快的梯度下降方法。
-
缺点:更新方向完全依赖于当前 batch,更新十分不稳定并且非常容易陷入局部极小值。如果使用过就会发现只需几次迭代就收敛到了一个比较差的点。如果损失函数是凸函数那么 SGD 无疑是非常合适的方法。
SGD with Momentum (SGDM)
\(v_{t+1} = \lambda v_t - \eta\nabla L(\theta_t)\)
\(\theta_{t+1} = \theta_t + v_{t+1}\)
或者
\(v_{t+1} = \lambda v_t + \eta\nabla L(\theta_t)\)
\(\theta_{t+1} = \theta_t - v_{t+1}\)
特点:使用动量模拟运动的惯性。更稳定,更快,有一定摆脱局部最优的能力。
缺点:会很快冲过最小值点。最后收敛的时候比较慢。但是在一些应用场景中,SGDM 可以收敛到一个比较好的值。
Nesterov accelerated gradient (NAG)
\(v_{t+1} = \lambda v_t - \eta\nabla L(\theta_t+\lambda v_t)\)
\(\theta_{t+1} = \theta_t + v_{t+1}\)
特点:和标准动量方法相比,唯一的不同是计算动量时使用的是下一时刻的梯度。那么如果下一时刻走到了一个不太好的地方就会及时止损,而如果走到了一个比较好的地方就会加速下降。
缺点:相当于多了一整个 forward 和 backward 过程,计算非常慢。实际中用的都是该方法的变形
\(v_{t+1} = \lambda v_t - \eta\nabla L(\theta_t)\)
\(\theta_{t+1} = \theta_t + \lambda v_{t+1} - \eta\nabla L(\theta_t)\)
可以证明这两种方法是完全等价的(令\(\theta_t^*=\theta_t+\lambda v_t\),带入第一组式子即可)。
预备知识
在介绍接下来的优化器时,需要先了解指数加权平均。
指数加权平均 (Exponentially weighted average)
\(v_{t+1}=\beta v_t + (1-\beta)\theta_t\)
这是一种保持记忆的方式。记忆项本质是指数衰减的,记忆窗口的长度可视作\(\frac{1}{1-\beta}\),因为可以证明
\(\beta\)越大,记忆窗口的长度越大,越平滑。
带偏差修正的指数加权平均 (bias correction / debiased in exponentially weighted average)
\(v_{t+1}=\beta v_t + (1 - \beta)\theta_t\)
\(\tilde v_t = \frac{v_t}{1-\beta^t}\)
简单的指数加权平均在前几项时,会有很大的误差。因为前几项没有填满滑动窗口,而缺失的值都默认为 0,这些 0 会对后面很长一段时间产生影响。因此加入了一个修正项使得:
- 在前几项使得\(v_{t+1}\)尽量接近\(\theta_t\)
- 之后使得\(v_{t+1}\)尽量接近\(\beta v_t + (1-\beta)\theta_t\)
这个修正项就是\(\tilde v_t = \frac{v_t}{1-\beta^t}\)
Adagrad
\(G_t = G_{t-1} + g_t^2\)
\(\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{G_t}+\epsilon}g_t\)
特点:之前的方法针对每一个参数使用相同的学习率,而 Adagrad 使得之前梯度较大的参数更新较慢,之前梯度较小的参数更新较慢。这样可以使得在平缓的方向上也能得到较快得下降,有一定摆脱局部最优的能力。
缺点:惩罚项累积太快,导致梯度很快消失。
RMSprop
\(v_{t+1}=\rho v_t + (1 - \rho)g_t^2\)
\(\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{v_{t+1}}}g_t\)
特点:解决了 Adagrad 梯度消失的问题
Adadelta
\(G_t = \rho G_{t-1} + (1-\rho)g_t^2\)
\(v_t = -\frac{\sqrt{V_t}}{\sqrt{G_t}}g_t\)
\(V_{t+1} = \rho V_t + (1 - \rho) v_t^2\)
\(\theta_{t+1} = \theta_t + v_{t+1}\)
特点:
- 解决了 Adagrad 梯度消失的问题
- 解决了 Adagrad 需要人工选取学习率的问题
- 解决了量纲不统一的问题
缺点:RMSprop 是 Adadelta 的特殊情况,效果差不多,而 Adadelta 内存和计算量都会大一些,并且没有 RMSprop 使用广泛。
Adam
\(m_{t+1} = \beta_1m_t + (1 - \beta_1)g_t\)
\(v_{t+1} = \beta_2v_t + (1 - \beta_2)g_t^2\)
\(\tilde m_t = \frac{m_t}{1-\beta_1^t}\)
\(\tilde v_t = \frac{v_t}{1-\beta_2^t}\)
\(\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\tilde v_{t+1}}+\epsilon}\tilde m_{t+1}\)
Nadam (Nesterov Adam)
\(\tilde m_t = \frac{\beta_1m_t}{1 - \beta_1^{t+1}}+\frac{(1-\beta_1)g_{t-1}}{1-\beta_1^t}\)
\(\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\tilde v_{t+1}}+\epsilon}\tilde m_{t+1}\)
特点:Adam 是一种结合了 momentum 和 RMSprop 的优化器。非常快,几乎最快。
关于\(\tilde m_t\)和\(\tilde v_t\)的解释,参考带偏差修正的指数加权平均 (bias-correction)。
Adam 缺点:最后收敛位置的泛化效果可能会低于 SGDM 等其他方法。一种可能的解释是 SGDM 更可能在一个比较平坦的极小值处 (Flat Minimum) 停下来,而 Adam 可能停在一个比较尖锐的极小值处 (Sharp Minimum)。
在训练末期,由于动量的记忆可以维持 \(\frac{1}{1-\beta_2}\) 这么多步,在这些步中有很大一部分都是乱走,只有几步是有效的更新,而有效的更新会被乱走(无效更新)的效果抵消。所以 Adam 不能收敛到一个比较好的结果。于是出现了几种的改进的思路:
- 让 Adam 收敛的效果好一点。如 AMSGrad,AdaBound
- 让 SGDM 收敛的速度快一点。如 Cyclical LR,SGDR,One-cycle LR
- 结合 Adam 和 SGDM。如 SWATS
前两种思路的主要方法都是调整自适应的学习率。
SWATS
先用 Adam 训练,再用 SGDM finetune。关键在于切换的时间和衔接的方法。
特点:简单粗暴。
缺点:简单粗暴。
AMSGrad
\(\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\tilde v_{t+1}}+\epsilon}\tilde m_{t+1}\)
\(\tilde v_t=\max(\tilde v_{t-1}, v_t)\)
特点:希望 Adam 在训练末期的有效更新不会被无效更新的效果抵消。解决了 gradient 小的时候 learning rate 太大的情况。
缺点:
- 没有解决 gradient 大的时候 learning rate 太小的情况
- 和 Adagrad 一样,惩罚项可能太大。
AdaBound
\(\theta_{t+1} = \theta_t - Clip(\frac{\eta}{\sqrt{\tilde v_{t+1}}+\epsilon})\tilde m_{t+1}\)
\(Clip(x) = Clip(x, 0.1-\frac{0.1}{(1-\beta_2)t+1}, 0.1+\frac{0.1}{(1-\beta_2)t})\)
特点:经验性的学习率裁剪
缺点:经验性的裁剪
Cyclical LR
直线上升,直线下降。形如三角波
特点:针对 SGDM 的学习率调整。大学习率用于快速训练,小学习率用于 fine tune。其他基于 SGD 的改进都是类似的学习率调整。
SGDR
瞬间上升,余弦下降。
One-cycle LR
只有一个 cycle 的学习率调整
关于 warm-up 的讨论
Q1:什么是 warm-up?
A1:warm-up 是在训练开始使用小学习率的一种技术。其可以使得在训练的初始阶段,梯度的变化更加平滑。
Q2:Adam 使用了偏差修正,还需要使用 warm-up 吗?
A2:需要。warm-up 可以使得前几个 epoch 的梯度变化比较平滑,这样后面自适应的学习率也会保持在一个比较平稳的水平。如果不使用 warm-up,梯度变化很大,会导致 RMS 惩罚项很大,训练速度会显著下降。
RAdam
\(\rho_t = \rho_\infty - \frac{2t\beta_2^t}{1 - \beta_2^t}\)
\(\rho_\infty = \frac{2}{1 - \beta_2} - 1\)
\(r_t = \sqrt{\frac{(\rho_t-4)(\rho_t-2)\rho_\infty}{(\rho_\infty-4)(\rho_\infty-2)\rho_t}}\)
When \(\rho_t \le 4\) (first few steps of training):
\(\theta_{t+1} = \theta_t - \eta\tilde m_{t+1}\)
When \(\rho_t > 4\):
\(\theta_{t+1} = \theta_t - \frac{\eta r_{t+1}}{\sqrt{\tilde v_{t+1}} + \epsilon}\tilde m_{t+1}\)
说明:
- \(\rho_\infty\)是有效记忆长度的一个估计。之前我们使用的有效记忆长度为\(\frac{1}{1-\beta}\),这里作者使用了两倍的这个值,那么衰减的大小就是 \(\frac{1}{e^2}\approx 0.135\)。
- \(r_t\)是近似\(\frac{Var(\frac{1}{v_\infty})}{Var(\frac{1}{v_t})}\),当 \(v_t\) 的方差很大时,说明走得很不稳定,所以要减小步长,此时 \(Var(\frac{1}{v_t})\) 也很大,\(r_t\) 就比较小;当 \(v_t\) 的方差很小时,说明走得很稳定,所以要增大步长,此时 \(Var(\frac{1}{v_t})\) 也很小,\(r_t\) 就比较大。
- 4 是 warm-up 的步数。这个结果不是 ad-hoc 的,而是因为 \(r_t\) 的近似结果中出现了 \(\rho_t-4\),说明这个估计在前几步是 invalid。所以干脆把这几步做成一个简单的 warm-up。
Lookahead
FOR t = 1, 2, ... (outer loop)
\(\theta_{t,0} = \phi_{t-1}\)
FOR i = 1, 2, ..., k (inner loop)
\(\theta_{t,i}=\theta_{t,i-1}+Optim(Loss, data, \theta_{t, i-1})\)
\(\phi_t = \phi_{t-1} + \alpha(\theta_{t,k}-\phi_{t-1})\)
说明:
Lookahead 是一个包装器,可以使用在任意优化器上面。本质就是,每走 k 步就往初始位置退回一点。\(\alpha\) 可以取 [0, 1] 之间任意值,只要不是非常接近端点,效果就不会太差。
- Lookahead 可以非常稳定。因为在比较崎岖的地方,Lookahead 很容易登上一个比较高的位置然后重新下降,因此很容易从这里逃离。另外如果有走向崎岖地方的趋势,Lookahead 也会及时退出。
- Lookahead 泛化性能非常好。原因同上。
关于 momentum 的一点说明
Q:对于包含正则化的 Loss,momentum 里面是不是应该包含正则化项的动量呢?
A:不要。正则化项的梯度直接更新 \(\theta_t\),不计入 momentum。同时改名为 Weight Decay,不再称作 Regularization。对应的优化器为 SGDWM 和 AdamW。
总结
-
优化器小结
Team SGD Team Adam SGD Adagrad SGDM RMSProp Learning rate scheduling Adadelta NAG Adam SGDWM AMSGrad AdaBound Learning rate scheduling RAdam Nadam AdamW -
使用建议
SGDM Adam Computer vision NLP Speech synthesis GAN Reinforcement learning
Reference:
- 李宏毅. 机器学习.公开课
- 天泽 28. 深度学习中优化方法.CSDN 博客