在深度学习领域,优化算法的选择是重中之重。梯度下降算法是目前神经网络中使用最广泛的优化算法之一。为了弥补朴素梯度下降的缺陷,又出现了SGD、SGD with Momentum、Adam、NAdam等。
深度学习优化算法经历了SGD->SGDM->NAG->AdaGrad->AdaDelta->Adam->Nadam 这样的发展历程。
SGD没有动量的概念,也就是说:
m t = g t ; V t = I 2 m_t=g_t; V_t=I^2 mt=gt;Vt=I2
带入步骤3,可以看到下降梯度就是最简单的:
η t = α ⋅ g t \eta_t=\alpha \cdot g_t ηt=α⋅gt
SGD最大的缺点是下降速度慢,而且可能会在沟壑的两边持续震荡,陷入局部最优点。
为了抑制SGD的震荡,SGDM认为梯度下降过程可以加入惯性。下坡的时候如果发现是陡坡,就可以利用惯性跑的更快一些。SGDM在SGD的基础上引入了一阶动量。
m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t m_t=\beta_1 \cdot m_{t-1}+(1-\beta_1) \cdot g_t mt=β1⋅mt−1+(1−β1)⋅gt
一阶动量是各个时刻梯度方向的指数移动平均值,约等于最近 个时刻的梯度向量和的平均值。
也就是说, t t t时刻的下降方向,不仅由当前点的梯度方向决定,而且由此前累积的下降方向决定。 β 1 \beta_1 β1的经验值为0.9,这就意味着下降方向主要是此前累积的下降方向,并略微偏向当前时刻的下降方向。想象高速公路上汽车转弯,在高速向前的同时略微偏向,急转弯可是要出事的。
除了下降速度慢,SGD还有一个问题是困在局部最优的沟壑里震荡。
想象一下你走到一个盆地,四周都是略高的小山,你觉得没有下坡的方向,那就只能待在这里了。可是如果你爬上高地,就会发现外面的世界还很广阔。因此,我们不能停留在当前位置去观察未来的方向,而要向前一步、多看一步、看远一些。
NAG 全称为 Nesterov Accelerated Gradient,是在SGD、SGD-M的基础上进一步改进,改进点在于步骤1。
我们知道在时刻t的主要下降方向是由累积动量决定的,自己的梯度方向说了也不算,那与其看当前梯度方向,不如先看看如果跟着累积动量走了一步,那个时候再怎么走。因此,NAG在步骤1,不计算当前位置的梯度方向,而是计算如果按照累积动量走了一步,那个时候的下降方向:
g t = ∇ f ( w t − α ⋅ m t − 1 ( V t − 1 ) ) g_t=\nabla f(w_t- \frac{\alpha \cdot m_{t-1}}{\sqrt(V_{t-1})}) gt=∇f(wt−(Vt−1)α⋅mt−1)
然后用下一个点的梯度方向,与历史累积动量相结合,计算步骤2中当前时刻的累积动量。
二阶动量的出现,才意味着“自适应学习率”优化算法时代的到来。SGD及其变种都是以同样的学习率更新参数,但深度神经网络往往包含大量的参数,对于经常更新的参数,我们已经积累了大量关于它的知识,不希望被单个样本影响太大,希望学习速率慢一些;对于偶尔更新的参数,我们了解它的信息太少,希望能从每个偶然出现的样本身上多学一些,即学习速率大一些。
二阶动量可以度量历史更新频率,二阶动量为迄今为止所有梯度值的平方和:
V t = ∑ τ = 1 t g τ 2 V_t=\sum^t_{\tau=1}g_\tau^2 Vt=τ=1∑tgτ2
由步骤3中的下降梯度:
η t = α ⋅ m t / V t \eta_t=\alpha \cdot m_t / \sqrt{V_t} ηt=α⋅mt/Vt
可知,此时的学习率实际上变成了 α / V t \alpha/\sqrt{V_t} α/Vt,一般为了避免分母为0,会在分母上加一个小的平滑项。当参数更新越频繁,二阶动量越大,学习率就越小。
这一方法在稀疏数据场景下表现非常好。但也存在一些问题:因为 V t \sqrt{V_t} Vt 是单调递增的,会使得学习率单调递减至0,可能会使得训练过程提前结束,即便后续还有数据也无法学到必要的知识。
由于AdaGrad单调递减的学习率变化过于激进,我们考虑一个改变二阶动量计算方法的策略:不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。这也就是AdaDelta名称中Delta的来历。
前面我们讲到,指数移动平均值大约就是过去一段时间的平均值,因此我们用这一方法来计算二阶累积动量:
V t = β 2 ∗ V t − 1 + ( 1 − β 2 ) g t 2 V_t=\beta_2*V_{t-1}+(1-\beta_2)g_t^2 Vt=β2∗Vt−1+(1−β2)gt2
这就避免了二阶动量持续累积、导致训练过程提前结束的问题了。
Adam 和 Nadam 是前述方法的集大成者。我们看到,SGD-M在SGD基础上增加了一阶动量,AdaGrad和AdaDelta在SGD基础上增加了二阶动量。把一阶动量和二阶动量都用起来,就是Adam了——Adaptive+Momentum。
参考文献:
[1] 一个框架看懂优化算法之异同 SGD/AdaGrad/Adam
[2] Gradient Descent with Momentum