当我们使用机器学习的时候,最开始都是初始化一组参数,然后不断优化迭代,得到最终的结果。所以优化算法也是机器学习中很重要的一个组成部分。
我们之前提到过的梯度下降法,牛顿法这些便是很经典的优化方法。
SGD
首先是stochastic Gradient Descent,随机梯度下降,简称SGD。每次选择一个mini-batch,而不是全部样本,使用梯度下降来更新模型参数。SGD最大的缺点是下降速度慢,而且可能会在沟壑的两边持续震荡,停留在一个局部最优点。
框架
基本上所有的优化算法都有一个固定的框架
首先我们定义待优化的参数为w ,目标函数为 f(w),初始的学习率为α。
而后,开始进行迭代优化。在每一轮(epoch)t:
1. 计算目标函数关于当前参数的梯度:
2. 根据历史梯度计算一阶动量和二阶动量:
3.计算当前时刻的下降梯度:
4.根据下降梯度进行更新:
一般来说,一阶动量m就是对于梯度进行操作,使他加上之前梯度的特征等等。二阶动量就是根据之前的梯度对于学习率进行一个自适应的变化。
我们拿着这个框架,来先对照一下sgd。sgd本身没有动量的概念,所以m直接等于梯度
SGDM
SGDM即为SGD with momentum,它加入了动量机制,1986年提出。
在SGD基础上引入了一阶动量:
一阶动量是各个时刻梯度方向的指数移动平均值,约等于最近 1/(1-β1) 个时刻的梯度向量和的平均值。
由此可见t迭代的动量,其实是前t-1迭代的梯度的加权和。β为衰减权重,越远的迭代权重越小。从而我们可以发现,SGDM相比于SGD的差别就在于,参数更新时,不仅仅减去了当前迭代的梯度,还减去了前t-1迭代的梯度的加权和。由此可见,SGDM中,当前迭代的梯度,和之前迭代的累积梯度,都会影响参数更新。
t 时刻的下降方向,不仅由当前点的梯度方向决定,而且由此前累积的下降方向决定。β1的经验值为0.9,这就意味着下降方向主要是此前累积的下降方向,并略微偏向当前时刻的下降方向。想象高速公路上汽车转弯,在高速向前的同时略微偏向,急转弯可是要出事的。
NAG
NAG为Nesterov Accelerated Gradient,
是在SGD、SGD-M的基础上的进一步改进,改进点在于步骤1。我们知道在时刻t的主要下降方向是由累积动量决定的,自己的梯度方向说了也不算,那与其看当前梯度方向,不如先看看如果跟着累积动量走了一步,那个时候再怎么走。因此,NAG在步骤1,不计算当前位置的梯度方向,而是计算如果按照累积动量走了一步,那个时候的下降方向:
然后用下一个点的梯度方向,与历史累积动量相结合,计算步骤2中当前时刻的累积动量。
AdaGrad
Sgd系列的算法大部分都是对于一阶动量进行修改操作。这些算法都有一个问题就是学习率如果设置的过高,那么就不容易收敛好,如果过低,就收敛的太满。于是便有了二阶动量,即对于学习率进行自适应更新。
AdaGrad设置二阶动量为
该维度上,迄今为止所有梯度值的平方和:
带入步骤三
可以看出,此时实质上的学习率由变成了。 一般为了避免分母为0,会在分母上加一个小的平滑项。因此是恒大于0的,而且参数更新越频繁,二阶动量越大,学习率就越小。
这一方法在稀疏数据场景下表现非常好。但也存在一些问题:因为是单调递增的,会使得学习率单调递减至0,可能会使得训练过程提前结束,即便后续还有数据也无法学到必要的知识。
RMSProp
由于AdaGrad单调递减的学习率变化过于激进,我们考虑一个改变二阶动量计算方法的策略:不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。
修改的思路很简单。前面我们讲到,指数移动平均值大约就是过去一段时间的平均值,因此我们用这一方法来计算二阶累积动量:
就避免了二阶动量持续累积、导致训练过程提前结束的问题了。
Adam
我们看到,SGD-M在SGD基础上增加了一阶动量,AdaGrad和AdaDelta在SGD基础上增加了二阶动量。把一阶动量和二阶动量都用起来,就是Adam了——Adaptive + Momentum。
SGD的一阶动量:
加上AdaDelta的二阶动量:
优化算法里最常见的两个超参数,都在这里了,前者控制一阶动量,后者控制二阶动量。
一般现在最常用的优化方法就是sgdm与adam。两相对比,
Adam的训练更快,不够稳定,有着更大的泛化差。
Sgdm则更加稳定,泛化差距小,但是训练速度会比较慢。