本文介绍机器学习中不同优化算法之间的差异。
大概步骤
首先用一个框架来梳理所有的优化算法
定义
待优化参数: $ w $
目标函数: $ f(w) $
初始学习率 $ \alpha $
进行迭代优化
在每个epoch $ t $ ,进行如下步骤:
- 计算目标函数关于当前参数的梯度: $ g_t=\nabla f(w_t) $
- 根据历史梯度计算一阶动量和二阶动量:$ m_t = \phi(g_1, g_2, \cdots, g_t) $;$ V_t = \psi(g_1, g_2, \cdots, g_t) $
- 计算当前时刻的下降梯度: $ \eta_t = \dfrac {\alpha}{\sqrt{V_t}} \cdot m_t $
- 根据下降梯度进行更新: $ w_{t+1} = w_t - \eta_t $
步骤3、4对于各个算法都是一致的,主要的差别就体现在1和2上。
比较
优化算法 | 区别 | 优点 | 缺点 |
---|---|---|---|
$ \mathrm{SGD} $ | 没有动量的概念 $ \eta_t = \alpha \cdot g_t $ |
1. 下降速度慢 2.可能会在沟壑的两边持续震荡,停留在一个局部最优点 |
|
$ \mathrm{SGDM(SGD with Momentum)} $ | 在SGD基础上引入了一阶动量: $ m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1)\cdot g_t $ $ \beta_1 $的经验值为0.9,这就意味着下降方向主要是此前累积的下降方向,并略微偏向当前时刻的下降方向。 一阶动量是各个时刻梯度方向的指数移动平均值(EMA),约等于最近 $ 1/(1-\beta_1) $ 个时刻的梯度向量和的平均值。 |
为了抑制SGD的震荡,SGDM认为梯度下降过程可以加入惯性。下坡的时候,如果发现是陡坡,那就利用惯性跑的快一些 | |
$ \mathrm{NAG(Nesterov Accelerated Gradient)}$ | 在步骤1,不计算当前位置的梯度方向,而是计算如果按照累积动量走了一步,那个时候的下降方向: $ g_t=\nabla f(w_t - \dfrac { \alpha }{ \sqrt{V_{t-1}} } \cdot m_{t-1}) $ 然后用下一个点的梯度方向,与历史累积动量相结合,计算步骤2中当前时刻的累积动量。 |
||
$ \mathrm{AdaGrad} $ | SGD及其变种以同样的学习率更新每个参数,但深度神经网络往往包含大量的参数,这些参数并不是总会用得到(想想大规模的embedding)。对于经常更新的参数,我们已经积累了大量关于它的知识,不希望被单个样本影响太大,希望学习速率慢一些;对于偶尔更新的参数,我们了解的信息太少,希望能从每个偶然出现的样本身上多学一些,即学习速率大一些。 怎么样去度量历史更新频率呢?那就是二阶动量该维度上,迄今为止所有梯度值的平方和: $ V_t = \sum_{\tau=1}^{t} g_\tau^2 $ $ \eta_t = \dfrac {\alpha}{\sqrt{V_t}} \cdot g_t $ |
在稀疏数据场景下表现非常好 | 因为$ \sqrt{V_t} $ 是单调递增的,会使得学习率单调递减至0,可能会使得训练过程提前结束,即便后续还有数据也无法学到必要的知识 |
$ \mathrm{AdaDelta} $ | 主要修改了第3步 learning rate是自己算出来的 $ E_t = \gamma \cdot E_{t-1} + (1-\gamma) \eta_t^2 $ $ \eta_t = \dfrac { \sqrt{ E _{t-1} } } { \sqrt{V_t} } \cdot g_t $ |
避免了二阶动量持续累积、导致训练过程提前结束的问题了 | |
$ \mathrm{RMSProp} $ | 由于AdaGrad单调递减的学习率变化过于激进,我们考虑一个改变二阶动量计算方法的策略: 不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。 这也就是AdaDelta名称中Delta的来历。 修改的思路很简单。前面我们讲到,指数移动平均值大约就是过去一段时间的平均值,因此我们用这一方法来计算二阶累积动量: $ V_t = \beta_2 * V_{t-1} + (1-\beta_2) g_t^2 $ $ \eta_t = \dfrac {\alpha}{\sqrt{V_t}} \cdot g_t $ |
避免了二阶动量持续累积、导致训练过程提前结束的问题了 | |
$ \mathrm{Adam} $ | 把一阶动量和二阶动量都用起来,就是Adam了——Adaptive + Momentum $ m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1)\cdot g_t $ $ V_t = \beta_2 * V_{t-1} + (1-\beta_2) g_t^2 $ |
学习速度快 | 泛化能力不好 |
$ \mathrm{Nadam} $ | Nesterov + Adam = Nadam $ g_t=\nabla f(w_t - \dfrac { \alpha }{ \sqrt{V_{t-1}} } \cdot m_{t-1}) $ |
指数移动平均值的偏差修正
前面我们讲到,一阶动量和二阶动量都是按照指数移动平均值进行计算的:
$ m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1)\cdot g_t $
$ V_t = \beta_2 \cdot V_{t-1} + (1-\beta_2) \cdot g_t^2 $
实际使用过程中,参数的经验值是:$ \beta_1=0.9 $, $ \beta_2=0.999 $
初始化:$ m_0=0 $, $ V_0=0 $
这个时候我们看到,在初期, $ m_t $, $ V_t $ 都会接近于0,这个估计是有问题的。因此我们常常根据下式进行误差修正:
$ \tilde{m}_t = \dfrac {m_t}{1-\beta_1^t} $ , $ \tilde{V}_t = \dfrac {V_t}{1-\beta_2^t} $
NAG与普通momentum的区别
Tip
一般在CV(computer Vision)中用SGD+Momentum比自适应算法效果好,部分文章中提到的Momentum默认为Nesterov momentum