深度学习中各种优化方法的原理和比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)
梯度下降法(英语:Gradient descent)是一个一阶最优化算法,通常也称为最速下降法。 要使用梯度下降法找到一个函数的局部极小值,必须向函数上当前点对应梯度(或者是近似梯度)的反方向的规定步长距离点进行迭代搜索。如果相反地向梯度正方向迭代进行搜索,则会接近函数的局部极大值点;这个过程则被称为梯度上升法。
梯度下降算法(Gradient Descent Optimization)是神经网络模型训练最常用的优化算法。对于深度学习模型,基本都是采用梯度下降算法来进行优化训练的。
SGD - Stochastic gradient descent (SGD) 随机梯度下降法,根据每一条训练示例 x (i)和标签 label y (i)执行参数更新 :
θ = θ − η · ∇θJ(θ; x (i) ; y (i) )
批量梯度下降为大型数据集执行了冗余计算,因为它会在参数更新前重新计算类似示例的梯度。 SGD通过每执行一次更新一次参数来取消了这种冗余,从而在在线学习上会有更快的速度。但是会导致目标函数的波动很大,如下图所示:
SGD很难通过陡谷,即在一个维度上的表面弯曲程度远大于其他维度的区域[19],这种情况通常出现在局部最优点附近。在这种情况下,SGD摇摆地通过陡谷的斜坡,同时,沿着底部到局部最优点的路径上只是缓慢地前进,这个过程如图a:
如图2b所示,动量法[16]是一种帮助SGD在相关方向上加速并抑制摇摆的一种方法。动量法将历史步长的更新向量的一个分量γγ增加到当前的更新向量中(部分实现中交换了公式中的符号)
vt=γvt−1+η∇θJ(θ)vt=γvt−1+η∇θJ(θ)
θ=θ−vt
动量项γγ通常设置为0.9或者类似的值。
从本质上说,动量法,就像我们从山上推下一个球,球在滚下来的过程中累积动量,变得越来越快(直到达到终极速度,如果有空气阻力的存在,则γ<1γ<1)。同样的事情也发生在参数的更新过程中:对于在梯度点处具有相同的方向的维度,其动量项增大,对于在梯度点处改变方向的维度,其动量项减小。因此,我们可以得到更快的收敛速度,同时可以减少摇摆。
Adagrad
AdaGrad 会在学习的过程中自动调整 learning rate, 对于出现频率低的参数使用较大的 learning rate, 出现频率高的参数使用较小的 learning rate. 因此, 这种方法对于训练数据比较稀疏的情况比较适用. AdaGrad 可以提高 SGD 的鲁棒性
Adagrad是一种基于梯度的优化算法:让学习率适应参数,对于出现次数较少的特征,我们对其采用更大的学习率,对于出现次数较多的特征,我们对其采用较小的学习率。因此,Adagrad非常适合处理稀疏数据。Dean等人[6]发现Adagrad能够极大提高了SGD的鲁棒性并将其应用于Google的大规模神经网络的训练,其中包含了YouTube视频中的猫的识别。此外,Pennington等人利用Adagrad训练Glove词向量,因为低频词比高频词需要更大的步长。
前面,我们每次更新所有的参数θθ时,每一个参数θiθi都使用的是相同的学习率ηη。由于Adagrad在tt时刻对每一个参数θiθi使用了不同的学习率,我们首先介绍Adagrad对每一个参数的更新,然后我们对其向量化。为了简洁,令gt,igt,i为在tt时刻目标函数关于参数θiθi的梯度:
gt,i=∇θJ(θi)
在tt时刻,对每个参数θiθi的更新过程变为:
θt+1,i=θt,i−η⋅gt,I
对于上述的更新规则,在tt时刻,基于对θiθi计算过的历史梯度,Adagrad修正了对每一个参数θiθi的学习率:
其中,Gt∈Rd×dGt∈Rd×d是一个对角矩阵,对角线上的元素i,ii,i是直到tt时刻为止,所有关于θiθi的梯度的平方和(Duchi等人[7]将该矩阵作为包含所有先前梯度的外积的完整矩阵的替代,因为即使是对于中等数量的参数dd,矩阵的均方根的计算都是不切实际的。),ϵϵ是平滑项,用于防止除数为0(通常大约设置为1e−81e−8)。比较有意思的是,如果没有平方根的操作,算法的效果会变得很差。
由于GtGt的对角线上包含了关于所有参数θθ的历史梯度的平方和,现在,我们可以通过GtGt和gtgt之间的元素向量乘法⊙⊙向量化上述的操作:
θt+1=θt−ηGt+ϵ−−−−−√⊙gtθt+1=θt−ηGt+ϵ⊙gt
Adagrad算法的一个主要优点是无需手动调整学习率。在大多数的应用场景中,通常采用常数0.010.01。
Adagrad的一个主要缺点是它在分母中累加梯度的平方:由于没增加一个正项,在整个训练过程中,累加的和会持续增长。这会导致学习率变小以至于最终变得无限小,在学习率无限小时,Adagrad算法将无法取得额外的信息。接下来的算法旨在解决这个不足。
Adadelta
Adadelta 是Adagrad的一种扩展算法,以处理Adagrad学习速率单调递减的问题。不是计算所有的梯度平方,Adadelta将计算计算历史梯度的窗口大小限制为一个固定值ww。
在Adadelta中,无需存储先前的ww个平方梯度,而是将梯度的平方递归地表示成所有历史梯度平方的均值。在tt时刻的均值E[g2]tE[g2]t只取决于先前的均值和当前的梯度(分量γγ类似于动量项):
我们将γγ设置成与动量项相似的值,即0.90.9左右。为了简单起见,我们利用参数更新向量ΔθtΔθt重新表示SGD的更新过程:
我们先前得到的Adagrad参数更新向量变为:
现在,我们简单将对角矩阵GtGt替换成历史梯度的均值E[g2]tE[g2]t:
由于分母仅仅是梯度的均方根(root mean squared,RMS)误差,我们可以简写为:
作者指出上述更新公式中的每个部分(与SGD,动量法或者Adagrad)并不一致,即更新规则中必须与参数具有相同的假设单位。为了实现这个要求,作者首次定义了另一个指数衰减均值,这次不是梯度平方,而是参数的平方的更新:
因此,参数更新的均方根误差为:
由于RMS[Δθ]tRMS[Δθ]t是未知的,我们利用参数的均方根误差来近似更新。利用RMS[Δθ]t−1RMS[Δθ]t−1替换先前的更新规则中的学习率ηη,最终得到Adadelta的更新规则:
使用Adadelta算法,我们甚至都无需设置默认的学习率,因为更新规则中已经移除了学习率。
特点:
训练初中期,加速效果不错,很快
训练后期,反复在局部最小值附近抖动
Adam
自适应矩估计(Adaptive Moment Estimation,Adam)是另一种自适应学习率的算法,Adam对每一个参数都计算自适应的学习率。除了像Adadelta和RMSprop一样存储一个指数衰减的历史平方梯度的平均vtvt,Adam同时还保存一个历史梯度的指数衰减均值mtmt,类似于动量:
mtmt和vtvt分别是对梯度的一阶矩(均值)和二阶矩(非确定的方差)的估计,正如该算法的名称。当mtmt和vtvt初始化为0向量时,Adam的作者发现它们都偏向于0,尤其是在初始化的步骤和当衰减率很小的时候(例如β1β1和β2β2趋向于1)。
通过计算偏差校正的一阶矩和二阶矩估计来抵消偏差:
正如我们在Adadelta和RMSprop中看到的那样,他们利用上述的公式更新参数,由此生成了Adam的更新规则:
作者建议β1β1取默认值为0.90.9,β2β2为0.9990.999,ϵϵ为10−810−8。他们从经验上表明Adam在实际中表现很好,同时,与其他的自适应学习算法相比,其更有优势。
特点:
结合了Adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点
对内存需求较小
为不同的参数计算不同的自适应学习率
也适用于大多非凸优化 - 适用于大数据集和高维空间
Adamax:针对Adam做过优化的算法,
此方法对学习率的上限提供了一个更简单的范围。公式上的变化如下:
Nadam
Nadam类似于带有Nesterov动量项的Adam。公式如下:
Nadam对学习率有了更强的约束,同时对梯度的更新也有更直接的影响。一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。
测试代码:
Loss对比图:
测试Accuracy 对比图:
训练 Accuracy 对比图:
参考:
https://arxiv.org/pdf/1609.04747.pdf
https://cs.stanford.edu/people/karpathy/convnetjs/demo/trainers.html
http://www.matthewzeiler.com/wp-content/uploads/2017/07/googleTR2012.pdf
https://blog.csdn.net/u013709270/article/details/78667531
- 点赞
- 收藏
- 关注作者
评论(0)