梯度下降算法综述

目录:

  • 简介梯度下降算法。
  • 介绍梯度下降算法的不同变体。
  • 总结在优化过程面临的一些挑战。
  • 介绍最常见的梯度优化算法。
  • 总结

简介梯度下降算法:

梯度下降法是最常用的优化算法之一,也是迄今为止优化神经网络最常用的方法之一。同时,每个最先进的深度学习库都包含各种优化梯度下降算法的实现。然而,这些算法通常被称作黑盒优化器,因为很难找到对其优缺点的实际解释。本文旨在为读者提供有关优化梯度下降的不同算法的区别与联系,使得它更好的为我们所用。

梯度下降法是一种不断调整模型参数\theta来最小化目标函数J(\theta ),通过在目标函数\triangledown_{\theta }J(\theta)梯度的相反方向更新参数来最小化目标函数J(\theta ),学习率η决定了我们达到(局部)最小值的步骤的大小。换言之,我们沿着目标函数产生的曲面坡度的方向下坡,直到到达一个山谷。

介绍梯度下降算法的不同变体:

根据它们在计算目标函数梯度时所用的数据量不同。将梯度下降算法分为3种,“批量梯度下降算法”、“随机梯度下降算法”、“小批量梯度下降算法”。根据数据量的不同,我们在参数更新的准确性和执行更新所需的时间之间进行权衡。

  • 批量梯度下降算法

Vanilla gradient descent,又名batch gradient descent(批量梯度下降算法),以下简称BGD,它在计算目标函数梯度时使用全部训练样本,参数更新公式为\theta = \theta - \eta \ast \triangledown_{\theta }J(\theta),通常要预先设定参数更新的迭代次数。因为我们需要计算整个数据集的梯度,以便只执行一次更新,批量梯度下降可能非常慢,并且对大数据集来说是很难处理的。批量梯度下降也不允许我们在线更新我们的模型。虽然很慢但往往这种方法参数更新的方向是快的方向。

然后我们按照梯度的方向更新参数,学习率决定我们参数更新的步伐。对于凸误差曲面,批量梯度下降保证收敛到全局最小值,对于非凸曲面保证收敛到局部最小值。

 

  • 随机梯度下降算法

Stochastic gradient descent(随机梯度下降),以下简称SGD,它对每个训练示例x^{i}和标签y^{i}执行参数更新,遍历样本集,每遇到一个样本便更新一次参数。

批处理梯度下降对大型数据集执行冗余计算,因为它在每个参数更新之前重新计算类似示例的梯度。SGD通过一次执行一次更新来消除这种冗余。因此,它通常要快得多,也可以用于在线学习。但SGD执行频繁的高方差更新,导致目标函数剧烈波动,如下图所示:

梯度下降算法综述_第1张图片

当批量梯度下降收敛到参数所在的局部最小值时,一方面,SGD的波动使其能够跳到新的、可能更好的局部极小值。另一方面,这最终会使收敛到精确最小值变得复杂,因为SGD可能由于某个误差使得梯度更新过大跳过最小值点。然而,当我们缓慢地降低学习速率时,SGD表现出与批梯度下降相同的收敛行为,几乎可以肯定地分别收敛到非凸和凸优化的局部或全局最小值。总的来说BGD更新参数速度较慢,但每一步都能保证参数更新的较为准确,而SGD更新速度较快,但受误差数据影响较大,肯会出现较差的更新。

 

  • 小批量梯度下降算法

Mini-batch gradient descent(小批量梯度下降算法)最终将两者优点兼得,并为每一个小批量n个训练示例执行更新:

具体做法是将样本集划分成若干个批次,每个批次常见的大小在50到256之间,但可能因不同的应用而有所不同,在每个批次上执行批量梯度下降算法。在训练神经网络时,小批量梯度下降是典型的选择算法,当使用小批量时,通常也使用SGD这个术语。

优化过程面临的一些挑战:

 

然而,小批量梯度下降算法并不能保证很好的收敛性,但它提供了一些需要解决的挑战:

  • 选择一个合适的学习率是很困难的。学习速率太小会导致收敛速度非常慢,而学习速率太大则会阻碍收敛,并导致损失函数在最小值附近波动甚至发散。
  • 学习速率表试图通过动态调整等方法在训练期间调整学习率,即根据预先定义的时间表降低学习率,或者当不同时期之间的目标变化低于阈值时。然而,这些时间表和阈值必须事先定义,因此无法适应数据集的特性。
  • 此外,将相同的学习率应用于所有参数更新。如果我们的数据是稀疏的,并且我们的特征具有非常不同的频率,我们可能不希望将所有这些更新到相同的程度,而是对很少出现的特征执行更大的更新。
  • 最小化神经网络常见的高度非凸误差函数的另一个关键挑战是避免陷入大量次最小。Dauphin等人认为困难实际上不是来自局部极小值(实际上局部极限值出现的概率是很低的,它要求每个维度在该带点都处于局部最小值,通常我们数据集的维度是较大的),而是来自鞍点,即一个维度向上倾斜,另一个维度向下倾斜的点。这些鞍点通常被一个具有相同误差的平台所包围,这使得SGD很难逃脱,因为梯度在所有维度都接近于零。

其中(0,0)就是一个鞍点: 

梯度下降算法综述_第2张图片

常见的梯度优化算法:

  •  Momentum

SGD在穿越沟壑时遇到了困难,即表面在一个维度上的曲线比在另一个维度上要陡得多,这在局部最优点附近很常见。在这些情况下,SGD在沟谷斜坡上振荡,而沿着谷底向局部最优方向缓慢前进;如下图所示,我们的参数在2个方向上的梯度一个较大,一个较小,这就造成这两个方向的总方向像黑色箭头那样,而实际上我们希望看到的方向为红色的箭头,因为沿着红色箭头可以更快到达我们的最优点。

梯度下降算法综述_第3张图片

黑色箭头很容易造成下列震荡的现象出现:

梯度下降算法综述_第4张图片

Momentum(动量)是一种有助于在相关方向上加速SGD并抑制振荡的方法,如下图所示。它通过在当前更新向量上添加过去更新向量的γ倍(γ也被称为动量项)来实现这一点(如上图所示,实际更新的方向会在最优更新方向上左右震荡,Momentum做法的好处是利用上一次更新方向来抵消一部分当前更新方向偏离最优更新方向的幅度,以达到减小震荡的目的。):

梯度下降算法综述_第5张图片梯度下降算法综述_第6张图片

动量项γ通常设置为0.9或者一个更小的值。

另外一种解释:

 常规SGD的做法中,一个球沿着斜坡滚下山,小球滚动过程中在某些点的梯度为0,但该点可能不是全局最优点仅仅是局部最优点,于是小球便陷入该点,这显然不是我们希望看到。Momentum的做法给小球一个惯性能够成功越过这个局部最优点,从而可以成功的找到全局最优点。

 

  • Nesterov accelerated gradient

以下简称NAG,它是在Momentum基础上的改进。然而,一个球滚下山,盲目地沿着斜坡,是非常不令人满意的。我们希望有一个更聪明的球,一个知道它要去哪里的球,这样它就知道在再次上坡之前要减速。以下是NAG的梯度更新公式:

梯度下降算法综述_第7张图片

下面我将用一张图来解释上面的梯度更新公式,我们知道常规的Momentum做法是:每一次下降的方向为当前梯度方向和上一次梯度方向的总方向,那么既然这样,我为什么不提前走到超前点C呢,再计算C点的梯度下降方向,通过B->C的方向(即:上一次0.9倍A点梯度下降方)和C->D(即:C点梯度下降方向),这两个方向的和便能到达实际下降点D,而不用去计算B的梯度下降反向。

是为了得到C点的梯度方向,通过当前点B减掉0.9倍上一次梯度方向便得到C点,在计算C点的偏微分就拿到了C点的梯度下降方向。将C点的梯度下降方向与0.9倍A点的梯度下降方向的总方向,便可以成功到达实际点D。

梯度下降算法综述_第8张图片

对于NAG这个做法,很多文章给出的解释是,能够让算法提前看到前方的地形梯度,如果前面的梯度比当前位置的梯度大,那我就可以把步子迈得比原来大一些,如果前面的梯度比现在的梯度小,那我就可以把步子迈得小一些。这个大一些、小一些,都是相对于原来不看前方梯度、只看当前位置梯度的情况来说的。但相比传统的Momentum方法,NAG方法收敛速度明显加快,波动也小了很多。 

  • Adagrad

梯度下降算法综述_第9张图片

梯度下降算法综述_第10张图片

 Adagrad的做法是动态更新学习率,学习率与当前的时间成反比,与此同时学习率除以一个过去所有更新过梯度的均方,这样做的好处是如果前面的梯度都比较大会让梯度慢慢降低下来,如果前面的梯度都比较小会让我当前的梯度慢慢增加上去。

上面的梯度更新公式还可以写成如下形式:

在很多论文中,会在分母中加上一个\varepsilon,它是一个平滑项,可避免被零除(通常为1e−8)。

看到这,可能都会有一个疑问, 在梯度下降算法中我梯度比较大对应我的参数应该有较大的的更新;而在Adagrad表达式中,分子有一个很大的梯度表示要给参数一个较大的更新,但在分母上也有当前较大的梯度,又表示给我当前参数一个较小的更新,这不是矛盾嘛?

梯度下降算法综述_第11张图片

这其实不是矛盾的,下面通过直观方面和数学方面给出解释:

直观的解释:

梯度下降算法综述_第12张图片

 比如我过去的梯度分别为0.001、0.001、0.003、0.002,这时我相比得到一个0.1较大的梯度,而分母记录了过去较小的梯度,分子作为当前最新的梯度,可以造成反差的效果。

数学方面的解释:

梯度下降算法综述_第13张图片

在参数\omega _{1}方向上,损失函数图像坡度是比较小的,而在\omega _{2}方向上坡度是比较大的;a点我有较小的梯度但同时距离最优点(0,0)是比较远的,而在c点拥有较大的梯度却距离最优点(0,0)是较远的,这显然不是合理的。Adagrad的表达式要表达的是在一点参数更新的幅度不仅与当前点的梯度成正比,还要和当前点所在的坡度成反比,坡度即该点的二次偏导,

梯度下降算法综述_第14张图片

而二次梯度可以用过去所有出现梯度的均方近似表示,这就不难理解Adagrad公式为什么是这样的了。

 

  • Adadelta

Adadelta是Adagrad的一个扩展,它试图降低它的激进型,来解决AdaGrad算法中存在的缺陷,下面来看看Adagrad存在的一些优缺点:

  • 优点

学习率将随着梯度的倒数增长,也就是说较大梯度具有较小的学习率,而较小的梯度具有较大的学习率,可以解决普通的SGD方法中学习率一直不变的问题。

  • 缺点

还是需要自己手动指定初始学习率,而且由于分母中对历史梯度一直累加,学习率将逐渐下降至0,并且如果初始梯度很大的话,会导致整个训练过程的学习率一直很小,从而导致学习时间变长。

改进方法一(Accumulate Over Window):

  • 在一个窗口w中对梯度进行求和,而不是对梯度一直累加。
  • 因为存放 w 之前的梯度是低效的,所以可以用对先前所有梯度均值(使用RMS即均方根值实现)的一个指数衰减作为代替的实现方法。

更新公式如下:
① 将累计梯度信息从全部历史梯度变为当前时间向前的一个窗口期内的累积:

相当于历史梯度信息的累计乘上一个衰减系数\rhoρ,然后用(1 - \rhoρ)作为当前梯度的平方加权系数相加,这样做的好处让历史的梯度信息慢慢衰减,而非慢慢累积使得训练过程的学习率慢慢变小。

②然后将上述E[g_t^2]开方后,作为每次迭代更新后的学习率衰减系数:

即:

 这种更新方法确实解决了对历史梯度一直累加而导致学习率一直下降的问题,但还是要人为确定初始的学习率。

改进方法二(Correct Units with Hessian Approximation):

介绍这种方法前先引出二阶牛顿迭代公式。

  • 二阶牛顿迭代公式:

牛顿法的基本思想:利用迭代点处的一阶导数(梯度)和二阶导数(Hessian矩阵)对目标函数进行二次函数近似,然后把二次模型的极小点作为新的迭代点,并不断重复这一过程,直至求得满足精度的近似最小值。

牛顿法的更新公式,基于二阶泰勒展开

然后对上式求导,并令,得到更新公式:

我们知道在二阶泰勒展开式中,xx^{(0)}越接近,该表达式越准确。并且,我们在前面介绍Adagrad的时候,Adagrad的表达式要表达的是在一点参数更新的幅度不仅与当前点的梯度成正比,还要和当前点所在的坡度成反比,坡度即该点的二次偏导。此时通过二阶优化算法如牛顿法,将二阶导数作为分母加入更新参数,使得在梯度变化过快方向相对梯度变化慢的方向更新尺度发生改变,从而解决病态问题。

AdaDelta算法改进方法二正是采用了这种思想:

x_{t+1} - x_{t} = \Delta x \approx \frac{\frac{\partial f}{\partial x}}{\frac{\partial ^{2}f}{\partial x^{2}}}

于是用RMS来近似: 

\frac{1}{\frac{\alpha ^{2}f}{\alpha x^{2}}} = \frac{\Delta x}{\frac{\alpha f}{\alpha x}} \approx -\frac{RMS[\Delta x]_{t-1}}{RMS[g]_{t}}

然后:

 \Delta x = -\frac{RMS[\Delta x]_{t-1}}{RMS[g]_{t}}\cdot g_{t}

注意:分子为RMS[\Delta x]_{t-1}而不是RMS[\Delta x]_{t},此刻\Delta x_{t}还没有计算出来。

总结AdaDelta算法梯度更新公式(不需要设置默认的学习速率):

梯度下降算法综述_第15张图片

Adadelta参考自:这篇博客

  • RMSprop

RMSprop是Hinton在其课程中提出的一种未发表的自适应学习率方法。RMSprop和Adadelta都是在同一时间被独立提出来的,它们都是为了解决Adagrad急剧下降的学习率问题(Adagrad由于分母中对历史梯度一直累加,学习率将逐渐下降至0,并且如果初始梯度很大的话,会导致整个训练过程的学习率一直很小)。RMSprop实际上与我们上面推导的Adadelta的第一个更新向量相同:

梯度下降算法综述_第16张图片

RMSprop还将学习速率除以平方梯度的指数衰减平均值。Hinton建议将\gamma设置为0.9,而学习速率\eta的良好默认值为0.001。

  • Adam

自适应矩估计以下简称Adam,它是另一种计算每个参数的自适应学习率的方法。除了存储过去平方梯度的指数衰减平均值v_{t}(如Adadelta和RMSprop),Adam还保持了过去梯度m_{t}的指数衰减平均值,类似于Momentum(动量)。Adam结合AdaGradRMSProp两种优化算法的优点。对梯度的一阶矩估计(First Moment Estimation,即梯度的均值)和二阶矩估计(SecondMoment Estimation,即梯度的未中心化的方差)进行综合考虑,计算出更新步长:

梯度下降算法综述_第17张图片

m_{t}v_{t}分别是梯度的一阶矩(平均值)和二阶矩(无中心方差)的估计值,因此该方法的名称。由于m_{t}v_{t}被初始化为0的向量,Adam的作者观察到它们偏向于零,特别是在初始时间步长期间,尤其是当衰减率很小(即β1和β2接近1)时,即初始值影响较大,随着时间t的增加m_{t}v_{t}增加缓慢。他们通过计算偏差修正的一阶矩和二阶矩估计值来抵消这些偏差:

梯度下降算法综述_第18张图片

初始阶段t=1,2...,m_{t}v_{t}都除以分母为一个小于1的一个较小值,可以保证m_{t}v_{t}不会偏向于0。然后,他们使用这些来更新参数,正如我们在Adadelta和RMSprop中看到的一样,这产生了Adam更新规则:

提出者建议\beta _{1}的默认值为0.9,\beta _{2}的默认值为0.999,\varepsilon的默认值为10^{-8};实践表明,Adam 比其他适应性学习方法效果要好。

  •  AdaMax

Adamax是Adam的一种变体,我们知道在Adam,它更新规则中的v_{t}根据过去梯度渐变v_{t-1}和当前梯度绝对值\left | g_{t} \right |^{2}渐变成反比缩放渐变:

更一般的形式: 

通常太大的范数p是极其不稳定的,这就是为什么L1范数和L2范数在实践中比较常见的原因。然而,\propto范数一般也表现出稳定的行为,为此,作者提出了AdaMax并证明了在\propto范数下v_{t}收敛到了稳定的值。这里为了避免与Adam混淆,我们使用u_{t}来表示这个稳定的值,可以进一步写成max()的形式:

梯度下降算法综述_第19张图片

现在用我们的u_{t}定义Adamax的更新规则:

由于u_{t}采用最大化过往的某一个梯度一定比例,所以,它不会出现偏向于0的情况发生,我们不需要对u_{t}的偏差校正。良好的默认参数值是\eta=0.002、\beta _{1}=0.9和\beta _{2}=0.999。

  • Nadam

我们知道Adam可以看作是RMSprop和Momentum的组合,RMSprop贡献了过去平方梯度的指数衰减平均值v_{t},而动量则是过去梯度m_{t}的指数衰减平均值。而我们现在要介绍的NAdam是NAG和Adam的结合体,为了将NAG合并到Adam中,我们需要修改它的动量项m_{t}

使用原始Momentum动量项m_{t}更新规则:

梯度下降算法综述_第20张图片

将上述式子展开:

这种写法再一次证明了更新是朝着前一个动量矢量的方向迈出一步,再朝着当前梯度的方向迈出一步。NAG告诉我们在计算梯度之前用动量步长更新参数,从而在梯度方向上执行更精确的步骤。因此,我们只需修改梯度g_{t}就是NAG:

梯度下降算法综述_第21张图片

接下来我们直接用m_{t-1}来更新当前参数,而不是使用m_{t-1}两次,一次用于更新梯度g_{t},第二次用于更新参数\theta _{t+1},上述式子写成:

梯度下降算法综述_第22张图片

我们现在使用当前动量向量m_{t},而不是在NAG那样动量向量m_{t-1}(上一次更新方向)来看的更远。为了给Adam添加NAG,我们可以类似地用当前动量向量替换先前的动量向量。

梯度下降算法综述_第23张图片

将上述式子展开:

\frac{m_{t-1}}{1-\beta _{1}^{t}}只是上一时间动量矢量m_{t-1}的偏差校正估计值。因此,我们可以用\hat{m_{t-1}}代替它:

同理我们现在使用当前动量向量m_{t},而不是在NAG那样动量向量m_{t-1}(上一次更新方向)来看的更远:

至此Nadam参数更新公式便得到了,如上式;上面的推导进一步说明了NAdam是NAG和Adam的结合体。

 

总结:

下列动图展示了上述几种梯度下降算法中使用不同的更新公式收敛速度:

梯度下降算法综述_第24张图片

  • 参考论文:https://arxiv.org/pdf/1609.04747.pdf

上述都是阅读该参考文献的翻译和总结,第一次总结难免出错,请各位大佬指正,后面会继续研究以做到循序渐进。

你可能感兴趣的:(机器学习,概率统计,算法的数学基础,人工智能,机器学习,深度学习,算法)