简介
优化算法在深度学习中也是十分重要的,虽然一般情况下无脑 Adam 即可,但有时采用其余的优化算法反而能够获得更好的结果,这点很有意思。同时,理解优化算法的原理对于选择和面试还是很有帮助的。
超参数设置 — 遵循原论文
优化算法 | 超参数 |
---|---|
SGD | |
Momentum | $\gamma: 0.9$ |
Adagrad | $\gamma: 0.9$ |
RMSprop/ Adadelta | |
Adam | $\beta_1: 0.9, \quad \beta_2: 0.999, \quad \epsilon: 1e-8$ |
Adamax | |
Nadam |
1. 三大基本算法
1. 随机梯度下降
2. 标准梯度下降
3. mini-batch 梯度下降
三者比较
- 随机梯度下降: 每次更新的方向并不向全局最优解的方向前进,最终的收敛结果也往往在全局最优解附近,但并不能达到最优解。迭代过程不可测。不容易陷入局部最小值。
- 标准梯度下降: 更新速度很慢,每次都要计算全部样本的梯度。且由于梯度方向过于稳定一致(没有随机因素)且更新次数过少,很容易陷入鞍点或局部最小值。
- mini-batch 梯度下降: 二者折中,batch size 的设置是一个艺术。
2. 梯度下降算法的一点改进
1. 动量梯度下降法
在使用梯度下降算法中,很容易产生一种“震荡现象”(相邻前后梯度正负相反),这种震荡现象减慢了梯度下降法的速度,这也导致你无法使用更大的学习率, 如果你使用较大的学习率, 可能导致震荡更大, 收敛更慢。
Momentum的核心思想: 通过计算梯度的指数加权平均值,并利用该平均值来更新你的权重,这样梯度的变化就没有那么快了。其本质是通过增加动量来减少随机,增加梯度的稳定性。
举个例子, 假如这里有个碗状的峡谷, 峡谷中坑坑洼洼,有许多小坡, 如果我们从峡谷上推下一个球, 根据物理现象,由于加速度,小球的速度在下降的过程中越来越快, 即使路上遇到小坡,也能够轻松跨越(跨不过去,就是局部最小点了), 直至到达谷底。
引申到动量法的参数变化中: 对于在梯度点处具有相同的方向的维度,表明加速度为正,那么速度自然加快;对于在梯度点处改变方向的维度, 加速度为负, 速度减缓。 这样,我们可以得到更快的收敛速度, 同时可以减少摇摆。
2. Nesterov Accelerated Gradient
思想: 在动量法中, 小球总是以一种盲目的方式滚动, 这会造成一个问题, 在临近最优点的附近时控制不住速度,于是会造成我们在最优点附近摇啊摇,最终收敛。
我们希望小球足够聪明,它能够预判后面的地形, 如果后面是下坡路就加速下降, 如果后面是上坡路,说明我们已经到了最优点附近, 该减速了。
实现方式:Nesterov就利用这一思想,它将 $J(\theta - \gamma v_{t-1})$ 假定为下一位置, 通过计算它的梯度,就可以得到我们接下来是加速还是刹车了,的确很聪明。
优点:Nesterov Accelerated Gradient 相比Momentum, 能显著的提升了优化效果,收敛速度要快很多。
我们来从数学角度分析一下, 相对 momentum, 到底发生了什么变化:
具体推论需要再次参考 比Momentum更快:揭开Nesterov Accelerated Gradient的真面目
3. 自适应学习率优化算法
0. 为何要自适应学习率?
在梯度下降的过程中,每个参数更新的频率与幅度是不同的,到了训练中后期,对于某些变量,也许已经到达了极小值附近,而有些变量仍然在初始位置不远处。 此时,如果我们采用不同的学习率会导致一个问题: 如果学习率偏小,则那些更新不多的参数会收敛的很慢,如果学习率偏大,那么对于处于极小值附近的参数,很容易产生不稳定现象。
为了解决这个问题,我们需要针对不同的参数设置不同的学习率, 但参数是无穷尽的, 不可能去人为的设置每一个参数的学习率,因此,自适应学习率就显得很有必要了。
1. Adagrad
$G_{i,t}$ 是一个对角矩阵, $G[i][i]$ 上的元素表示在第 t 步更新时, 历史上 $\theta$ 梯度的积累。
思想:对每个参数用不同的学习率,这个学习率在一开始比较大,用于快速梯度下降。随着优化过程的进行,对于已经下降很多的参数,则减缓学习率,对于还没怎么下降的参数,则保持一个较大的学习率。
方法: 通过维护一个对角矩阵来累积历史梯度来实现学习率的变化, 其中对角线上的每个元素表示某个参数历史梯度的累积。
如果某参数历史梯度较大,那么说明该参数优化的快,更有可能到达最优点附近, 而此时它在对角矩阵上对应的累积梯度也大, 从而使得对应的学习率较小,最终实现不同参数有着不同的学习率。
优点: 十分适合处理稀疏数据。消除了需要手动调整学习率的问题。
缺陷: 分母项的积累: 由于每个附加项都是正数,因此累积总和在训练期间不断增长。这反过来导致学习速率缩小并最终变得无限小,此时算法不再进行优化。
2. Adadelta
- $E[g^2]_t$ 表示 t 时刻的平方梯度对数平均值, 本质的思想用了对数平均的思路。
- 改进: 改进 Adagrad 中学习率最终无限小的问题。
- 思想: 通过设定一个窗口大小 w , 来求最近 w 个平方梯度的对数平均值(对数平均的思想),采用求平均值而非求和的方式可以有效的避免学习率无限低问题。
3. RMSprop
比较 RMSprop 与 Adadelta 二者公式可以发现,在 Adadelta 取 $\gamma = 0.9$ 就是RMSprop了。
4. Adam
- $m_t$ 是历史梯度的对数平均估计, $v_t$ 是历史梯度平方的对数平均估计,其实就是求取的$E[g_t], E[g_t^2]$ 的近似。
- $\hat{m_t}, \hat{v_t}$ 是对 $m_t, v_t$ 的校正,可以近似为对 $E[g_t], E[g_t^2]$ 的无偏估计。
我们结合 Momentum 与 RMSProp 算法来看, Adam算法本质上就是将二者结合,同时考虑到梯度与梯度平方, 通过历史梯度来加速收敛, 通过历史梯度平方来修正学习率。
优点: 高效的计算,收敛非常快。适合解决大规模数据和参数优化问题。
为何要进行偏差修正:
因为初始化的 $m_t$ 与 $v_t$ 为 0 向量,在通过指数平均计算均值时会偏差向 0, 尤其是在初始时间步中和 $\beta_1, \beta_2$ 非常小的情况下(接近于1),尤其如此。
更复杂的分析,推荐: 深度学习最常用的算法:Adam优化算法
5. AdaMax
6. Nadam
如何选择优化算法?
我个人一般选择 Adam, 优点是,收敛快,这样模型迭代起来也快, 如果是轻量级模型的话, 需要好好选择优化算法调参, 而如果是重量级的模型, 无脑 Adam 是一个相当不错的选择。
QA
1. 在mini-batch 中, batch size 会带来怎样的影响?
batch size 的大小往往是由多个因素决定的:
- 较大的批能得到更精确的梯度估计。
- 较小的批能带来更好的泛化误差,泛化误差通常在批大小为 1 时最好。但是,因为梯度估计的高方差,小批量训练时需要较小的学习率以保持稳定性,这意味着更长的训练时间。
- batch size 与所需显存息息相关,可参见:GPU 显存不足怎么办?
- 在 GPU 上, 请采用 2 的幂数作为 batch size, 一般取值在 32 - 256。
- 小批量更容易利用多核架构,但是太小的批并不会减少计算时间,这促使我们使用一些绝对最小批量
2. 深度学习为什么不用二阶优化?
目前深度学习中,反向传播主要是依靠一阶梯度。二阶梯度在理论和实际上都是可以应用都网络中的,但相比于一阶梯度,二阶优化会存在以下一些主要问题:
- 计算量大,训练非常慢。
- 二阶方法能够更快地求得更高精度的解,这在浅层模型是有益的。而在神经网络这类深层模型中对参数的精度要求不高,甚至不高的精度对模型还有益处,能够提高模型的泛化能力。
- 稳定性:二阶方法能更快求高精度的解,同样对数据本身要的精度也会相应的变高,这就会导致稳定性上的问题。
Reference
[1] An overview of gradient descent optimization algorithms