梯度下降优化算法
参考:https://blog.csdn.net/oppo62258801/article/details/103175179。
梯度下降优化算法
参考:https://blog.csdn.net/oppo62258801/article/details/103175179
论文:An overview of gradient descent optimization algorithms
梯度下降法及其变种
Batch gradient descent(批梯度下降法)
批梯度下降法(batch gradient descent)是指在整个训练数据集上求解损失函数关于参数θ的梯度:
θ = θ − η ∗ ▽ θ J ( θ ) \theta=\theta-\eta*\bigtriangledown_\theta J(\theta) θ=θ−η∗▽θJ(θ)
- η表示学习率,通常是一个较小的值,例如0.001,其决定我们将以多大的步长更新参数;
- ▽θJ(θ)表示损失函数在整个数据集上对参数θ计算一阶导数(取平均值)。因为是更新参数θ,所以计算θ的一阶导,一阶导方向是参数变化最快的方向。
由于每次更新时使用整个数据集计算所有梯度,因此计算速度非常慢,同时批梯度下降法不能在线更新模型,无法在运行过程中,增加新的样本。批梯度下降法代码如下:
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
[!CAUTION]
- 对于损失函数为凸函数的情况,批梯度下降法能够收敛到全局最小值;
- 对于损失函数为非凸函数的情况,批梯度下降法则能够收敛到局部最小值。
Stochastic gradient descent(SGD 随机梯度下降法)
批梯度下降法(stochastic gradient descent)是指使用每一条数据来计算梯度值更新参数:
θ = θ − η ∗ ▽ θ J ( θ ; x i ; y i ) \theta=\theta-\eta*\bigtriangledown_\theta J(\theta;x_i;y_i) θ=θ−η∗▽θJ(θ;xi;yi)
- η表示学习率,通常是一个较小的值,例如0.001,其决定我们将以多大的步长更新参数;
- ▽θJ(θ;xi;yi)表示损失函数在每一条数据上对参数θ计算一阶导数。因为是更新参数θ,所以计算θ的一阶导,一阶导方向是参数变化最快的方向。
通常,随机梯度下降法相比于批梯度下降法具有更快的速度,可用于在线学习,SGD以高方差频繁地更新,因此容易出现下列剧烈波动的情况。
SGD优化算法的特点:
- 相比于批梯度下降法可能使得损失函数陷入局部的缺点,SGD的波动性使得其有可能收敛到更好的局部最优,
- 这也使得SGD收敛到局部最小值的过程变得更加复杂,因为SGD一直在震荡。
与批梯度下降法的优化代码相比,SGD只是在训练的轮次中,每次选择一个训练样本时多了一个for循环。
for i in range(nb_epochs):
np.random.shuffle(data)
for example in data:
params_grad = evaluate_gradient(loss_function, example, params)
params = params - learning_rate * params_grad
Mini-batch gradient descent(小批量梯度下降法)
批量梯度下降法(mini-batch gradient descent)综合了上述两种方法的优点,在每次训练时使用 n 个小批量样本进行更新:
θ = θ − η ∗ ▽ ( θ ) J ( θ ; x i : i + n ; y i : i + n ) \theta=\theta-\eta*\bigtriangledown_{(\theta)J(\theta;x^{i:i+n};y^{i:i+n})} θ=θ−η∗▽(θ)J(θ;xi:i+n;yi:i+n)
该方法的特点:
- 可以以更小的方差来更新参数,参数收敛的过程波动更小;
- 获得比批梯度下降法更快的运行速度
训练神经网络模型,当使用小批量梯度下降法时,也将其称为SGD。 在下文提到的SGD,为了简单起见,我们省略了参数xi:i+n;yi:i+n
对于小批量梯度下降的代码,只在小批量数据上计算梯度:
for i in range(nb_epochs):
np.random.shuffle(data):
for batch in get_batches(data, batch_size=50):
params_grad = evaluate_gradient(loss_function, batch, params)
params = params - learning_rate*params_grd
从上面三种基本的梯度下降法可以看出,即使是小批量下降法也并不能保证模型参数达到很好的收敛效果,目前具有下面的问题(这也是后来的很多改进的优化算法改进的动力和方向):
- 选择一个合适的学习率是困难的。学习率太小会导致收敛太慢,太大会影响模型的收敛,有可能在最小值附近不断波动甚至偏离最小值。
- 对于不同的参数使用相同的学习率更新是不合理的。如果数据是稀疏的,就不能使用相同的学习率来更新了,对于出现次数少的特征,我们对其执行更大的学习率;(自适应)
- 高度非凸误差函数普遍出现在神经网络中,在优化这类函数时,另一个关键的挑战是使函数避免陷入无数次优的局部最小值。Dauphin等人指出出现这种困难实际上并不是来自局部最小值,而是来自鞍点,即那些在一个维度上是递增的,而在另一个维度上是递减的。这些鞍点通常被具有相同误差的点包围,因为在任意维度上的梯度都近似为0,所以SGD很难从这些鞍点中逃开。(平坦的鞍点)
优化算法


we see the path they took on the contours of a loss surface (the Beale function). All
started at the same point and took different paths to reach the minimum. Note that Adagrad, Adadelta,
and RMSprop headed off immediately in the right direction and converged similarly fast, while
Momentum and NAG were led off-track, evoking the image of a ball rolling down the hill. NAG,
however, was able to correct its course sooner due to its increased responsiveness by looking ahead
and headed to the minimum.
shows the behaviour of the algorithms at a saddle point, i.e. a point where one dimension
has a positive slope, while the other dimension has a negative slope, which pose a difficulty for SGD
as we mentioned before. Notice here that SGD, Momentum, and NAG find it difficulty to break
symmetry, although the latter two eventually manage to escape the saddle point, while Adagrad,
RMSprop, and Adadelta quickly head down the negative slope, with Adadelta leading the charge.
Momentum-动量法
SGD很难通过陡谷,即在一个维度的表面弯曲程度远大于其他维度的区域,这种情况通常出现在局部最优点附近,这种情况下,SGD在不断波动下通过陡谷的斜坡,在沿着谷底到局部最优点的路径上缓慢前进,过程如下图(a)所示:

如上图(b)所示,动量法是一种帮助SGD在相关方向上加速并抑制摇摆的方法,利于处理非平稳梯度,动量法是将上一次更新量的一个分量γ增加到当前的更新量中,公式如下:
ν t = γ ν t − 1 + η ▽ θ J ( θ ) \nu_{t} = \gamma\nu_{t-1} + \eta\bigtriangledown_{\theta}J(\theta) \qquad νt=γνt−1+η▽θJ(θ)
θ = θ − v t \theta=\theta-v_\mathrm{t} θ=θ−vt
- 上面公式(1)等号后面,γ表示使用上次更新量的权重,决定了动量的大小,η部分跟前面SGD参数更新量完全相同;
- 公式(2)中,不再像前面SGD公式中直接将学习率大小体现出来了,而是整个的包含在νt中了。在后面的其他改进SGD的优化算法中也是类似的做法。
动量项γ通常可以设置成0.9。
可以这样来理解动量。参考文献[1]中这样的比喻很好:从山坡上往下推一个球,在往下滚动的过程中累积动量,速度越来越快,如果有空气阻力,则γ<1。对于参数更新也是如此,对于在当前梯度点处有相同方向的维度,动量项增加,对于在梯度点处改变方向的维度,其动量项减小,因此我们可以获得更快的收敛速度,同时可以减小频繁的波动。
Nesterov-加速梯度下降法
接着上面举的例子,如果球盲目的沿着斜率方向向下滚动,结果也不一定总是令人满意,我们希望有一个智能的球,能够知道它将要去哪,如果遇到斜率将要上升时,能够知道减速。
Nesterov加速梯度下降法(Nesterov accelerated gradient,NAG)是一种能够给动量项γνt−1一种预知能力的方法。我们使用动量项更新参数,通过计算θ - γνt−1能够告诉我们参数未来位置的一个近似值,也就是告诉我们参数将大致变为多少。通过计算参数未来的近似位置的梯度,即使用θ - γνt−1计算梯度,而不是使用θ来计算梯度,我们可以更加高效的求解(我自己理解为:这里的一次参数更新近似于动量法的两次更新,所以是加速了):
ν t = γ ν t − 1 + η ▽ θ J ( θ − γ ν t − 1 ) ( 3 ) θ = θ − ν t ( 4 ) \nu_{\mathrm{t}}=\gamma\nu_{\mathrm{t-1}}+\eta\bigtriangledown_{\mathrm{\theta}}J(\theta-\gamma\nu_{\mathrm{t-1}})\quad(3)\\\\\theta=\theta-\nu_{\mathrm{t}}\quad(4) νt=γνt−1+η▽θJ(θ−γνt−1)(3)θ=θ−νt(4)
上面公式(3)中,η部分,表示假设更新量为上次梯度上的动量大小,这是个近似更新量,然后再基于这个更新后的损失函数对于参数θ的一阶导数作为当前新的梯度,即公式(3)中η后面的部分。到这里就可以直接套用动量优化算法中公式(1)了,因此上面我理解为这种方式的一次参数更新的效果近似于动量法的两次参数更新的效果,所以理论上是加速了。
因为NAG-加速梯度下降法跟Momentum-动量法相似之处比较多,所以可以通过下面的一幅图对比两者的关系:
一般设置动量项γ的大小为0.9左右!
- 动量法:首先计算当前的梯度值(箭头线1),然后在更新的累积梯度上前进一大步(箭头线2);
- 加速梯度下降法:首先作一个预见性的更新,即在先前累积梯度方向上前进一大步(箭头线3),并计算出梯度作为一个修正(箭头线4),修正后为箭头线5。这里的预见性更新增强了算法的响应能力(即加速),同时通过修正防止了前进地太快。这一点对于很多RNN的任务的性能提升有着重要的意义。

对于上面的动量法和NAG法,是通过使参数更新适应损失函数的斜率以加速SGD;那么为了进一步优化,考虑使得参数的更新适应每一个单独参数,以根据每一个参数来决定是大的更新还是小的更新。这也是后面的优化算法设计的初衷。
Adagrad-自适应梯度
Adagrad是一种适应参数的梯度下降优化算法,其自适应性可以个性化到特征级别,出现次数较少的特征的,会使用更大的学习率,出现次数较多的特征,会使用较小的学习率,因此Adagrad适合于稀疏数据的深度神经网络模型。
- Dean等人[4]发现Adagrad能够极大提高了SGD的鲁棒性并将其应用于Google的大规模神经网络的训练,其中包含了YouTube视频中的猫的识别;
- Pennington等人[15]利用Adagrad训练Glove词向量,因为低频词比高频词需要更大的步长。
Agagrad在每次更新所有的参数θ时,对于每个参数使用不同的学习率,我们先看下如何对不同的参数进行更新的。下面公式(5)表示在t时刻损失函数关于参数θi的梯度:
g t , i = ▽ θ J ( θ i ) ( 5 ) \mathrm{g_{t,i}=\bigtriangledown_\theta J(\theta_i)}\quad(5) gt,i=▽θJ(θi)(5)
固定步长的学习率,则参数更新公式为:
θ t + 1 , i = θ t , i − η ∗ g t , i ( 6 ) \theta_{\mathrm{t+1,i}}=\theta_{\mathrm{t,i}}-\eta*g_{\mathrm{t,i}}\quad(6) θt+1,i=θt,i−η∗gt,i(6)
现在加入对不同参数个性化的步长因子,即在t时刻,基于对不同参数计算过的历史梯度,Adagrad修正了每一个参数的学习率:
θ t + 1 , i = θ t , i − η G t , i i + ϵ ∗ g t , i , Gt ∈ R d × d ( 7 ) \theta_{\mathrm{t+1,i}}=\theta_{\mathrm{t,i}}-\frac{\eta}{\sqrt{\mathrm{G_{t,ii}}+\epsilon}}\:*g_{t,i}\:,\quad\text{Gt}\in\mathbb{R^{d\times d}}\quad(7) θt+1,i=θt,i−Gt,ii+ϵη∗gt,i,Gt∈Rd×d(7)
其中,Gt是一个对角矩阵,对角线上的元素ii是从开始截止到t时刻为止,所有关于θi的梯度的平方和,Gt具体计算数值如下公式:
G t , i i = ∑ k = 1 t g k , i 2 ( 8 ) \mathrm{G_{t,ii}}=\sum_{k=1}^\mathrm{t}\mathrm{g_{k,i}}^2\mathrm{~(8)} Gt,ii=k=1∑tgk,i2 (8)
(Duchi等人将该矩阵作为包含所有先前梯度的外积的完整矩阵的替代,因为即使是对于中等数量的参数d,矩阵的均方根的计算都是不切实际的。)。ϵ是平滑项,用于防止除数为0(通常大约设置为1e−8)。
Adagrad优化算法中[6],如果没有平方根的计算,那么效果将会比较差。
现在我们将上面的公式向量化,主要为是为了简单。主要是将G和g之间的计算操作向量化,如下:
θ t + 1 = θ t − η G t + ϵ ⊙ g t ( 9 ) \theta_{\mathrm{t+1}}=\theta_\text{t}-\frac{\eta}{\sqrt{\mathrm{G_t}+\epsilon}}\odot\mathrm{g_t}\quad(9) θt+1=θt−Gt+ϵη⊙gt(9)
Adagrad算法的优缺点如下:
优点:主要优点就是无需手动调整学习率,基本上采用 0.01 即可。
缺点:由于其在分母中累加梯度的平方,每次增加一个正项,随着训练过程积累,会导致学习率越来越小,当学习率变得无限小时Adagrad算法将无法获得额外的信息更新。
下面将要介绍算法也是针对Adagrad的缺点进行改进的。
Adadelta
Adadelta算法完全移除了学习率,不再需要人工设置学习率参数。
Adadelta算法是Adagrad的一种扩展,以解决Adagrad学习速率单调递减的缺点。Adadelta算法无需存储历史梯度的平方和,而是将梯度的平方递归地表示成所有历史梯度的均值,因此在t时刻的均值只取决于先前的均值和当前的梯度:
E [ g 2 ] t = γ E [ g 2 ] t − 1 + ( 1 − γ ) g t 2 ( 10 ) \mathrm{E}[\mathrm{g}^2]_\mathrm{t}=\gamma\mathrm{E}[\mathrm{g}^2]_\mathrm{t-1}+(1-\gamma)\mathrm{g}_\mathrm{t}^2\quad(10) E[g2]t=γE[g2]t−1+(1−γ)gt2(10)
其中γ与动量项相似,可以设置成0.9。
对于参数更新向量我们可以表示成:
△ θ t = − η ⋅ g t , i ( S G D ) ( 11 ) △ θ t = − η G t + ϵ ⋅ g t ( A d a g r a d ) ( 12 ) \triangle\theta_{\mathrm{t}}=-\eta\cdot g_{\mathrm{t,i}}\quad(\mathrm{SGD})\quad(11)\\\triangle\theta_{\mathrm{t}}\:=-\frac{\eta}{\sqrt{\mathrm{G_{t}}+\epsilon}}\cdot\mathrm{g_{t}}\quad(\mathrm{Adagrad})\quad(12) △θt=−η⋅gt,i(SGD)(11)△θt=−Gt+ϵη⋅gt(Adagrad)(12)
那么,我们直接将Gt替换成历史梯度均值则为:
△ θ t = − η E [ g 2 ] t + ϵ ⋅ g t ( 13 ) \triangle\theta_\mathrm{t}=-\frac{\eta}{\sqrt{\operatorname{E}[\operatorname{g}^2]_\mathrm{t}+\epsilon}}\cdot\mathrm{g}_\mathrm{t}\quad(13) △θt=−E[g2]t+ϵη⋅gt(13)
上述公式中由于分母就是均方根,所以可以直接简写为:
△ θ t = − η R M S E [ g ] t ⋅ g t ( 14 ) \triangle\theta_\mathrm{t}=-\frac{\eta}{\mathrm{RMSE}[\mathrm{g}]_\mathrm{t}}\cdot\mathrm{g}_\mathrm{t}\quad(14) △θt=−RMSE[g]tη⋅gt(14)
Adadelta[7]直接指出了上述几种优化算法中更新规则与参数的单位不一致的问题,为此Adadelta实现了这个要求,类似于梯度的动量形式的均值,作者首次提出了参数的动量形式的均值,如下公式所示:
E [ △ θ 2 ] t = γ E [ △ θ 2 ] t − 1 + ( 1 − γ ) △ θ 2 ( 15 ) \operatorname{E}[\triangle\theta^2]_\mathrm{t}=\gamma\operatorname{E}[\triangle\theta^2]_\mathrm{t-1}+(1-\gamma)\triangle\theta^2\quad(15) E[△θ2]t=γE[△θ2]t−1+(1−γ)△θ2(15)
那么参数更新的均方根为:
R M S [ △ θ ] t = E [ △ θ 2 ] t + ϵ ( 16 ) \mathrm{RMS}[\triangle\theta]_\mathrm{t}=\sqrt{\mathrm{E}[\triangle\theta^2]_\mathrm{t}+\epsilon}\quad(16) RMS[△θ]t=E[△θ2]t+ϵ(16)
因为RMS[Δθ]t是未知的,所以近似取到t-1时刻的均方根来RMS[Δθ]t-1近似更新,并替换之前的固定值形式的学习率η,可以得到Adadelta的更新向量为:
△ θ t = − R M S [ △ θ ] t − 1 R M S E [ g ] t ⋅ g t ( 17 ) θ t = θ t + △ θ t ( 18 ) ( 18 ) ( 18 ) r e d ( 18 ) (18) a l i g n e d \triangle\theta_{\mathrm{t}}\:=-\frac{\mathrm{RMS}[\triangle\theta]_{\mathrm{t-1}}}{\mathrm{RMSE[g]_{\mathrm{t}}}\:\cdot g_{\mathrm{t}}\quad(17)\\\\\theta_{\mathrm{t}}\:=\:\theta_{\mathrm{t}}\:+\:\triangle\theta_{\mathrm{t}}\quad(18)\quad(18)\left(18\right)^{\mathrm{red}}\:(18) \text{(18)}{aligned}} △θt=−RMSE[g]t⋅gt(17)θt=θt+△θt(18)(18)(18)red(18)(18)alignedRMS[△θ]t−1
使用Adadelta优化算法,我们无需设置学习率,因为公式中已经移除了学习率的超参数。
RMSprop
RMSprop优化算法是Geoff Hinton提出来的一种自适应学习率的算法,与Adadelta几乎同时提出来的,是Adadelta的一个特例。
RMSprop与Adadelta一样,都是去解决Adagrad的学习率下降太快的问题的,参数更新公式如下:
E [ g 2 ] t = 0.9 E [ g 2 ] t − 1 + 0.1 g t 2 (19) θ t + 1 = θ t − η E [ g 2 ] t + ϵ g t (20) \mathrm{E}[\mathrm{g}^{2}]_{\mathrm{t}}=0.9\mathrm{E}[\mathrm{g}^{2}]_{\mathrm{t-1}}+0.1\mathrm{g}_{\mathrm{t}}^{2} \text{(19)}\\\\\theta_{\mathrm{t+1}}=\theta_{\mathrm{t}}-\frac{\eta}{\sqrt{\mathrm{E}[\mathrm{g}^{2}]_{\mathrm{t}}+\epsilon}}\mathrm{g}_{\mathrm{t}} \text{(20)} E[g2]t=0.9E[g2]t−1+0.1gt2(19)θt+1=θt−E[g2]t+ϵηgt(20)
因此,RMSprop也是将学习率分解成平方梯度的指数衰减的平均,对于学习率η,建议选择 0.001。
Adam-自适应矩估计
自适应矩估计(Adaptive Moment Estimation, Adam)也是一种会对每一个参数会计算出自适应学习率的算法。它一个动量算法和RMSprop算法的结合体,既考虑到了利用动量项来加速训练过程,又考虑到对于学习率的约束。Adam也会计算出来一个指数衰减的历史平方梯度的平均vt ,Adam同时还计算一个指数衰减的历史梯度的平均mt,类似于动量:
m t = β 1 m t − 1 + ( 1 − β 1 ) g t ( 21 ) v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 ( 22 ) \mathrm{m_t=\beta_1m_{t-1}+(1-\beta_1)g_t}\quad(21)\\\mathrm{v_t~=\beta_2v_{t-1}+(1-\beta_2)g_t^2\quad(22)} mt=β1mt−1+(1−β1)gt(21)vt =β2vt−1+(1−β2)gt2(22)
因此,mt是对梯度的一阶矩的估计,νt是对梯度的二阶矩(非确定性误差)的估计。
但是当mt和νt都初始化为0时,特别是在初始化的步骤和衰减率都很小时(β1和β2接近于1),Adam比较接近于0,这对于参数更新并不友好(更新太慢),Adam中是通过计算偏差矫正的一阶矩估计和二阶矩估计来抵消偏差的,公式如下:
m ^ t = m t 1 − β 1 t ( 23 ) v ^ t = v t 1 − β 2 t ( 24 ) \hat{\mathrm{m}}_{\mathrm{t}}=\frac{\mathrm{m}_{\mathrm{t}}}{1-\mathrm{\beta}_{1}^{\mathrm{t}}}\quad(23)\\\\\hat{\mathrm{v}}_{\mathrm{t}}\:=\frac{\mathrm{v}_{\mathrm{t}}}{1-\mathrm{\beta}_{2}^{\mathrm{t}}}\quad(24) m^t=1−β1tmt(23)v^t=1−β2tvt(24)
至此,生成Adam的参数更新公式如下:
θ t + 1 = θ t − η ν ^ t + ϵ m ^ t ( 25 ) \theta_{\mathrm{t+1}}=\theta_{\mathrm{t}}-\frac{\eta}{\sqrt{\hat{\nu}_{\mathrm{t}}}+\epsilon}\hat{m}_{\mathrm{t}}\quad(25) θt+1=θt−ν^t+ϵηm^t(25)
Adam作者建议β1、β2分别取默认值0.9、0.999就好,ϵ为10−8。
从经验上来看,Adam在实际任务中表现更好(哈哈,其他人的经验)。
通过上面对Adam的理解,可以看出来,Adam结合了Adagrad善于处理稀疏梯度和Momentum善于处理非平稳目标的优点,相较于其他几种优化器效果更好。
AdaMax
AdaMax优化算法是对Adam算法的更新。
Adam算法中,使用到了参数的指数衰减的梯度平方的平均,即:
v t = β 2 v t − 1 + ( 1 − β 2 ) ∣ g t ∣ 2 ( 26 ) v_\mathrm{t}=\beta_2v_{t-1}+(1-\beta_2)|g_\mathrm{t}|^2\quad(26) vt=β2vt−1+(1−β2)∣gt∣2(26)
对上面的公式进行扩展到ℓp范数,同时也将β2 扩展到βp2,上面公式变为:
v t = β 2 p v t − 1 + ( 1 − β 2 p ) ∣ g t ∣ p ( 27 ) v_\mathrm{t}=\beta_2^\mathrm{p}v_{t-1}+(1-\beta_2^\mathrm{p})|g_\mathrm{t}|^\mathrm{p}\quad(27) vt=β2pvt−1+(1−β2p)∣gt∣p(27)
在这里,AdaMax用到了范数的相关形性质,即通常大p值的范数通常具有数值不稳定性,因此我们更常见到的是1范数和2范数,但是无穷范数除外,当p趋于无穷时,范数具有较好的数值稳定性。
因此,AdaMax的作者提出了使用无穷范数的AdaMax优化算法,并且使用了ℓ∞的vt能够收敛到一个外稳定的值,为了避免和上面的Adam优化算法搞混淆,我们使用ut来代替vt作为参数更新的表示:
u t = β 2 ∞ v t − 1 + ( 1 − β 2 ∞ ) ∣ g t ∣ ∞ = max ( β 2 ν t − 1 , ∣ g t ∣ ) ( 28 ) \mathrm{u_t~=\beta_2^\infty v_{t-1}+(1-\beta_2^\infty)|g_t|^\infty}\\\\=\max(\beta_2\nu_{t-1},|g_t|)\quad(28) ut =β2∞vt−1+(1−β2∞)∣gt∣∞=max(β2νt−1,∣gt∣)(28)
根据上面的参数更新向量放到前面Adam的参数更新公式中,即为:
θ t + 1 = θ t − η u t m t ^ ( 29 ) \theta_{\mathrm{t+1}}=\theta_{\mathrm{t}}-\frac{\eta}{\mathrm{u_t}}\hat{\mathrm{m_t}}\quad(29) θt+1=θt−utηmt^(29)
对公式(28)中,由于取的是最大值的计算操作,因此不用像在Adam中担心参数更新量趋近于0的问题,因此在AdaMax中也不需要进行偏差矫正的操作。
AdaMax中的超参数,一般比较好的默认是η=0.002、β1=0.9、β2=0.999。
Nadam-加速自适应矩估计
Adam算法结合了RMSprop优化算法和动量优化算法的优点:
- RMSprop产生指数衰减的平方梯度的均值vt;
- 动量算法产生指数衰减的平方梯度的均值mt。
在上面介绍到的各种优化算法中,我们可以看到NAG算法优于动量优化算法。
基于此,Nadam结合了Adam算法和NAG算法,为了能够将NAG算法应用于Adam公式中,我们需要修改NAG算法的动量部分mt。
这里我们再来看下动量算法、NAG的对动量的改进算法的逻辑:
先是动量优化算法-Momentum:
g t = ▽ θ J ( θ ) (30) m t = γ m t − 1 + η g t (31) θ t + 1 = θ t − m t (32) \mathrm{g_{t}}=\bigtriangledown_{\theta}\mathrm{J}\left(\theta\right) \text{(30)}\\\mathrm{m_{t}}=\gamma\mathrm{m_{t-1}}+\mathrm{\eta g_{t}} \text{(31)}\\\mathrm{\theta_{t+1}}=\mathrm{\theta_{t}}-\mathrm{m_{t}} \text{(32)} gt=▽θJ(θ)(30)mt=γmt−1+ηgt(31)θt+1=θt−mt(32)
将公式(31)带入公式(32)得到如下:
θ t + 1 = θ t − ( γ m t − 1 + η g t ) ( 33 ) \theta_{\mathrm{t+1}}=\theta_{\mathrm{t}}-(\gamma\mathrm{m}_{\mathrm{t-1}}+\mathrm{\eta g}_{\mathrm{t}})\quad(33) θt+1=θt−(γmt−1+ηgt)(33)
从公式(33)容易看出,Momentum优化算法包括在历史累积梯度方向上前进一步、在当前梯度方向上前进一步。
再是NAG加速动量优化算法:
g t = ▽ θ J ( θ − γ m t − 1 ) (34) m t = γ m t − 1 + η g t (35) θ t + 1 = θ t − m t (36) \mathrm{g_{t}}=\bigtriangledown_{\theta}\mathrm{J}\left(\theta-\gamma\mathrm{m}_{t-1}\right) \text{(34)}\\\mathrm{m_{t}~=\gamma m_{t-1}~+\eta g_{t}} \text{(35)}\\\mathrm{\theta_{t+1}~=~\theta_{t}~-m_{t}} \text{(36)} gt=▽θJ(θ−γmt−1)(34)mt =γmt−1 +ηgt(35)θt+1 = θt −mt(36)
NAG算法在计算梯度前就先使用动量步骤来更新参数,因此NAG跟Momentum的区别就是计算梯度gt上的差别。
基于上面两个基本的动量方向的优化算法的逻辑,引出Nadam算法:
相比于NAG算法的有两个使用动量的步骤-其一是更新梯度gt,其二是更新参数θt+1,我们现在使用look-ahead方式的动量直接更新当前参数:
g t = ▽ θ J ( θ ) (37) m t = γ m t − 1 + n g t (38) θ t + 1 = θ t − ( γ m t + η g t ) (39) \mathrm{g_{t}}=\bigtriangledown_{\theta}\mathrm{J}\left(\theta\right) \text{(37)}\\\mathrm{m_{t}}=\gamma\mathrm{m_{t-1}}+\mathrm{ng_{t}} \text{(38)}\\\\\theta_{\mathrm{t+1}}=\theta_{\mathrm{t}}-(\gamma\mathrm{m_{t}}+\mathrm{\eta g_{t}}) \text{(39)} gt=▽θJ(θ)(37)mt=γmt−1+ngt(38)θt+1=θt−(γmt+ηgt)(39)
可以对比和公式(39)和公式(33),可以看到他们唯一的区别是look-ahead方式中的动量更新中使用了截止到当前t的动量mt,而在NAG的参数更新规则中使用的截止到t-1的动量mt−1。我们可以通过类比将历史动量向量替换为当前动量向量的方式,来将NAG算法特点应用在Adam算法中,Adam的原始更新规则为:
m t = β 1 m t − 1 + ( 1 − β 1 ) g t ( 40 ) m t ^ = m t 1 − β 1 t ( 41 ) θ t + 1 = θ t − η v t 2 + ϵ m t ^ ( 42 ) \mathrm{m_{t}}=\beta_{1}\:\mathrm{m_{t-1}}\:+\:(1-\beta_{1}\:)\mathrm{g_{t}}\quad(40)\\\hat{\mathrm{m_{t}}}\:=\frac{\mathrm{m_{t}}}{1-\beta_{1}^{\mathrm{t}}}\quad(41)\\\mathrm{\theta_{t+1}}\:=\:\theta_{t}\:-\:\frac{\mathrm{\eta}}{\sqrt{\mathrm{v_{t}}^{2}\:+\epsilon}}\hat{\mathrm{m_{t}}}\quad(42) mt=β1mt−1+(1−β1)gt(40)mt^=1−β1tmt(41)θt+1=θt−vt2+ϵηmt^(42)
将上面公式(41)中的mt带入得到公式(42)的展开式如下:
θ t + 1 = θ t − η v t 2 + ϵ ( β 1 max t − 1 1 − β 1 t + ( 1 − β 1 ) g t 1 − β 1 t ) ( 43 ) β 1 max t − 1 1 − β 1 t ( 44 ) β 1 max t − 1 1 − β 1 t − 1 ( 45 ) \theta_{\mathrm{t+1}}=\theta_{\mathrm{t}}-\frac{\eta}{\sqrt{\mathrm{v}_{\mathrm{t}}^{2}}+\epsilon}(\frac{\beta_{1}\max_{\mathrm{t-1}}}{1-\beta_{1}^{\mathrm{t}}}+\frac{(1-\beta_{1})g_{\mathrm{t}}}{1-\beta_{1}^{\mathrm{t}}})\quad(43)\\\frac{\beta_1\max_{\mathrm{t-1}}}{1-\beta_1^{\mathrm{t}}}\quad(44)\\\\\frac{\beta_1\max_{\mathrm{t-1}}}{1-\beta_1^{\mathrm{t-1}}}\quad(45) θt+1=θt−vt2+ϵη(1−β1tβ1maxt−1+1−β1t(1−β1)gt)(43)1−β1tβ1maxt−1(44)1−β1t−1β1maxt−1(45)
上面的公式(44)模块为上一步骤的动量估计的偏差修正,尽管公式(45)才是准确的对于上一步骤的动量估计的偏差修正,但是为了简单起见,此处我们忽略掉公式(44)和(45)在分母上的区别,所以公式(43)可以转化为:
θ t + 1 = θ t − η ν t 2 + ϵ ( B 1 m ^ t − 1 + ( 1 − β 1 ) g t 1 − β 1 t ) ( 46 ) \theta_{\mathrm{t+1}}=\theta_\text{t}-\frac{\eta}{\sqrt{\nu_\text{t}^2}+\epsilon}(\text{B}_1\hat{m}_{\mathrm{t-1}}+\frac{(1-\beta_1)g_t}{1-\beta_1^t})\quad(46) θt+1=θt−νt2+ϵη(B1m^t−1+1−β1t(1−β1)gt)(46)
到这里,可以对比一下公式(46)和公式(39)了,类比于在公式(39)中用当前动量替代前一个步骤的动量的做法,我们将Nesterov Momentum的思想引入到Adam中了,最终参数更新规则如下:
θ t + 1 = θ t − η ν t 2 + ϵ ( β 1 m ^ t + ( 1 − β 1 ) g t 1 − β 1 t ) ( 46 ) \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{\nu_{t}^{2}}+\epsilon}\left(\beta_{1}\hat{m}_{t}\:+\frac{(1-\beta_{1})g_{t}}{1-\beta_{1}^{\mathrm{t}}})\quad(46)\right. θt+1=θt−νt2+ϵη(β1m^t+1−β1t(1−β1)gt)(46)
Which optimizer to use
So, which optimizer should you use? If your input data is sparse, then you likely achieve the best
results using one of the adaptive learning-rate methods. An additional benefit is that you will not
need to tune the learning rate but will likely achieve the best results with the default value.
In summary, RMSprop is an extension of Adagrad that deals with its radically diminishing learning
rates. It is identical to Adadelta, except that Adadelta uses the RMS of parameter updates in the
numerator update rule. Adam, finally, adds bias-correction and momentum to RMSprop. Insofar,
RMSprop, Adadelta, and Adam are very similar algorithms that do well in similar circumstances.
Kingma et al. [10] show that its bias-correction helps Adam slightly outperform RMSprop towards
the end of optimization as gradients become sparser. Insofar, Adam might be the best overall choice.
Interestingly, many recent papers use vanilla SGD without momentum and a simple learning rate
annealing schedule. As has been shown, SGD usually achieves to find a minimum, but it might take
significantly longer than with some of the optimizers, is much more reliant on a robust initialization
and annealing schedule, and may get stuck in saddle points rather than local minima. Consequently,
if you care about fast convergence and train a deep or complex neural network, you should choose
one of the adaptive learning rate methods.
Additional strategies for optimizing SGD
Shuffling and Curriculum Learning
Generally, we want to avoid providing the training examples in a meaningful order to our model as
this may bias the optimization algorithm. Consequently, it is often a good idea to shuffle the training
data after every epoch.
On the other hand, for some cases where we aim to solve progressively harder problems, supplying
the training examples in a meaningful order may actually lead to improved performance and better
convergence. The method for establishing this meaningful order is called Curriculum Learning [3].
Zaremba and Sutskever [21] were only able to train LSTMs to evaluate simple programs using
Curriculum Learning and show that a combined or mixed strategy is better than the naive one, which
sorts examples by increasing difficulty.
Batch normalization
To facilitate learning, we typically normalize the initial values of our parameters by initializing them
with zero mean and unit variance. As training progresses and we update parameters to different
extents, we lose this normalization, which slows down training and amplifies changes as the network
becomes deeper.
Batch normalization [9] reestablishes these normalizations for every mini-batch and changes are back-
propagated through the operation as well. By making normalization part of the model architecture,
we are able to use higher learning rates and pay less attention to the initialization parameters. Batch
normalization additionally acts as a regularizer, reducing (and sometimes even eliminating) the need
for Dropout.
Early stopping
According to Geoff Hinton: “Early stopping (is) beautiful free lunch”. You should thus always
monitor error on a validation set during training and stop (with some patience) if your validation error
does not improve enough.
Gradient noise
Neelakantan et al. [13] add noise that follows a Gaussian distribution N(0, σ2
t ) to each gradient
update:
g t , i = g t , i + N ( 0 , σ t 2 ) g_{t,i}=g_{t,i}+N(0,\sigma_t^2) gt,i=gt,i+N(0,σt2)
They anneal the variance according to the following schedule:
σ t 2 = η ( 1 + t ) γ \sigma_t^2=\frac{\eta}{(1+t)^\gamma} σt2=(1+t)γη
They show that adding this noise makes networks more robust to poor initialization and helps training
particularly deep and complex networks. They suspect that the added noise gives the model more
chances to escape and find new local minima, which are more frequent for deeper models.
更多推荐

所有评论(0)