深度模型中的优化——momentum|AdaGrad|RMSProp|Adam

在随机梯度下降中,沿着最速下降方向可以得到最快的下降速度:。其中,是下降步长,也被称为学习率

在常见的SGD算法中,批量梯度下降(BSGD)的算法如下:(引用《深度学习》(花书)P180)

算法:随机梯度下降(SGD)在第个训练迭代的更新


Require: 学习率

Require: 初始参数

while 停止准则未满足 do

从训练集中采样个样本,其中对应的目标为

计算梯度估计:

应用更新:

end while


PS:花书中把学习率记为 ,把收敛条件记为.

下降步长对梯度下降的影响

一个简单的例子:给定目标函数 ,初始点,其梯度(导数)为,给定步长,根据上文的更新公式计算,发现;继续进行下降更新,发现;如此反复,搜寻结果会反复在[-1, 1]之间横跳,且目标函数的值并不下降。

显然,随着训练的推进,我们应当逐渐减小下降步长。保证SGD收敛的一个充分条件是:

对于学习率/下降步长的选择设置,主要有以下两种情况:

对于BSGD,一个比较有意思的现象是当训练的批次样本较多时,他更容易收敛。在本文中我们只在一维上进行搜索,因此很容易出现不收敛的现象。

学习率优化算法的衡量标准

引入额外误差(excess error) ,即当前代价函数超出全局最小值的量。在凸问题中,SGD在步迭代之后的额外误差量级为,强凸情况下是

SGD学习率的提升方案

我们以为例子,先看看它的图像和梯度:(约定本文中所有的图横轴为迭代次数、纵轴为代价)

origin.png

线性衰减学习率

根据SGD的收敛充分条件,我们不难给定一个线性衰减的学习率,设定经过次迭代之后,令保持常数。既有:

通常,设定左右(令),即:;但的设定依旧容易带来函数收敛过程剧烈震荡或收敛过慢的问题,因此有更多优秀的自自适学习率算法被提出,在深度学习框架中有时把这些算法称为优化器

利用进行定步长SDG和衰减学习率的下降:

其函数图像如下(可以明显看到衰减学习率方案收敛得更快,但由于给定了大学习率,因此震荡更剧烈):

sgd.png

动量下降(momentum)

动量下降中引入了物理中惯性的概念,就像一个小球从山坡上滚下时,由于惯性的原因会直接冲过一些小坑,然后滚到山脚。在动量下降方案中,各超参数的更新规则如下:

算法:使用了动量下降方案的SGD


Require: 学习率、动量参数

Require: 初始参数、初始速度

while 没有达到停止准则 do

从训练集中采样个样本,其中对应的目标为

计算梯度估计:

计算速度更新:

应用更新:

end while


直观上理解,如果梯度的方向始终一致,那么SGD就会在这个方向上不停加速,将原步长每次放大为上一轮的倍。否则,会产生一个相反的惩罚:

momentum_fig.jpg

这样的好处就在于我们能够在一定情况下冲破局部最优点的陷阱,同时,面对较高的壁垒时比定步长SGD有更好的收敛性质。

在实践中,的取值一般为。利用python实现:

对比图像其实很难看到momentum在收敛性上相比于定步长SGD并没有什么太大的优点,甚至给定较大步长时也容易不收敛:

sgd_vs_momentum.png

但是,如果我们稍微换一个损失函数/目标函数,效果就会非常明显:(接下来的实验都将继续采用这个函数)

该新目标函数的图像如下,可以看到其有多个局部最优点:

new_loss.png

在区间中测量定步长SGD和momentum方案的性能,给定、二者一致的学习率

sgd_vs_momentum2.png

可以看到——在未经过细致调参的情况下,momentum方案冲破了第一个局部最优值继续下降;但是相对的,定步长SGD就没那么好运了(同样的,学习率线性衰减的SGD也会困于局部最优解)。所以,当我们提到SGD方案时,实际上往往用的是momentum及其改进方案,例如Keras框架就是这么做的。

Nesterov动量下降

为了改进momentum方案的额外误差收敛率,一个比较著名的变种是Nesterov动量下降:

算法:使用了Nesterov动量下降方案的SGD(花书P184)


Require: 学习率、动量参数

Require: 初始参数、初始速度

while 没有达到停止准则 do

从训练集中采样个样本,其中对应的目标为

应用临时更新:

计算梯度估计:

计算速度更新:

应用更新:

end while


它将额外误差收敛率从改进到了;但是在SGD的情况下,它并没有改进收敛率。

直观上理解,Nesterov方案比momentum方案多跨了一步,即,考虑得更多的是物理上的微分概念;在SGD的应用上,个人感觉并没有太大的性能改进表现,只在全批量下降时有着比较优秀的收敛性能。

AdaGrad

我们注意到,动量下降虽然在一定程度上优化了线性衰减的学习率和定步长SGD方案的弱点,但同时又引入了另一个超参数;而在实践中,超参数是一个非常难以确定的值。

所以我们希望学习率能在训练过程中进行自适应,即自我进行调整,以提升收敛率和降低收敛额外误差同时又不至于引入更多的超参数,减小调参的工作量。之前曾提过“成功失败法”,即Delta-bar-delta算法的变种,但缺点在于这类算法只有面对全批量下降时才比较有效。

而此处要介绍的AdaGrad算法,能够独立地适应所有模型参数的学习率,缩放每个参数反比于其所有梯度历史平方值总和的平方根。这么说可能过于拗口,我们直接看算法:

算法:AdaGrad算法(花书P188)


Require: 全局学习率

Require: 初始参数

Require: 小常数(防止进行除法时的值溢出)

初始化累积变量

while 没有达到停止准则 do

从训练集中采样个样本,其中对应的目标为

计算梯度估计:

累积平方梯度:

计算参数更新:

应用更新:

end while


花书中对AdaGrad的分析较少,但作为自适应学习率算法的入门算法,我觉得有必要进行一些分析:

得益于AdaGrad对梯度爆炸有着很好的抑制作用,所以实际上你可以给定一个很大的初始学习率,它在自我迭代的过程中也总能保证收敛。

adagrad.png

值得一说的是,AdaGrad在深度学习模型上表现得不错,比如采用64x64x1的全连接神经网络在波士顿房价回归问题上的表现如下:

sgd_adagrad_boston.png

RMSProp

在上面的图像中,AdaGrad在非凸情况下表现得并不好,收敛时震荡还是比较剧烈的。同时,如果你把上文中AdaGrad的初始学习率调小,你会发现AdaGrad会跟SGD一样困于某个局部最优值。造成AdaGrad面对梯度壁垒无能为力的可能性有很多,但最大的可能是搜索在到达一个局部洼地时学习率就收缩得太小了,因此导致搜寻的脚步深陷泥沼。

因此RMSProp改变梯度累积值为指数加权的移动平均值——抛弃过于遥远的历史,使其能够保证一定的跃出洼地泥沼的能力;但相对的,也会削弱其收敛率,在样本量较小时甚至完全不收敛。简单来说,就是把 改为 ,其中为衰减速率。

直观上理解,RSMProp的设计思路是这样的:梯度波动比较大的函数,它们的方差一定是非常大的,因此直接用梯度除以其二阶矩的开方,从而抑制了搜索时的摆动幅度。

算法:RMSProp算法(花书P188)


Require: 全局学习率、衰减速率

Require: 初始参数

Require: 小常数(防止进行除法时的值溢出)

初始化累积变量

while 没有达到停止准则 do

从训练集中采样个样本,其中对应的目标为

计算梯度估计:

累积平方梯度:

计算参数更新:

应用更新:

end while


运行结果如下:

rmsprop.png

有时候,还会为其加上Nesterov动量,使得其在某些问题上具有更好的性质:

算法:使用Nesterov动量的RMSProp算法(花书P189)


Require: 全局学习率、衰减速率、动量系数

Require: 初始参数、初始速度$v

Require: 小常数(防止进行除法时的值溢出)

初始化累积变量

while 没有达到停止准则 do

从训练集中采样个样本,其中对应的目标为

计算临时更新:

计算梯度估计:

累积平方梯度:

计算参数更新:

应用更新:

end while


我平常在应用时,并没有觉得二者有什么特别大的差别,因此老老实实用RMSProp就行了,还能少计算一些参数和引入超参数。可能对于一些较为疯狂的调参侠而言加了Nesterov,给了他们更多的微调空间。

Adam

Adam的词源来自adaptive moments,显然这又是一种动量方案和RMSProp的变种算法。从个人经验上来看,Adam往往更加地Robust,算是我用得比较多的一种优化方案。

算法:Adam算法(花书P189)


Require: 全局学习率

Require: 矩估计的指数衰减速率(建议默认0.9和0.9999)

Require: 初始参数

Require: 小常数(防止进行除法时的值溢出)

初始化时间序列、一阶和二阶矩变量

while 没有达到停止准则 do

从训练集中采样个样本,其中对应的目标为

计算梯度估计:

更新一阶矩估计:

更新二阶矩估计:

修正一阶矩偏差:

修正二阶矩偏差:

计算参数更新:

应用更新:

end while


观察这个算法,一阶矩和二阶矩可以简单理解成均值和方差,由于二者初始值都是,因此需要在刚开始时进行放大修正防止其向偏置。最后计算参数更新时,实际上用了一阶矩和二阶矩进行了估算。

矩估计可以看我的另外一篇文章:数理知识:参数估计——点估计、区间估计及置信区间

在吴恩达的公开课中,他给出他对Adam的理解,他认为Adam是momentum和RMSProp的一种结合:若把一个优化问题看成超空间上的谷地,搜索过程会在某个方向上来回摇摆,我们把这个方向记为纵轴;相反的,直达谷底的方向即为横轴。我们要做的就是抑制纵轴上的移动距离、加大在横轴上的移动距离。Adam和momentum对梯度的均值进行估计,使得纵轴上的摆动幅度减小;而对二阶矩即方差的抑制,可以进一步减小摇摆,相对的就是加大了横向搜索距离。

常用方案的对比总结

这里再快速回顾一下以上各种算法的特点。

算法名引入新的超参数容易困于洼地初始学习率/收敛率Cheat Sheet
线性衰减学习率可以较大
momentum较小
Nesterov较小
AdaGrad/
RMSProp较大
Adam