梯度下降优化算法综述

本文为“An overview of gradient descent optimization algorithms”一文翻译,仅供学习参考,强烈建议阅读原文

原文信息如下:
@article{DBLP:journals/corr/Ruder16,
author = {Sebastian Ruder},
title = {An overview of gradient descent optimization algorithms},
journal = {CoRR},
volume = {abs/1609.04747},
year = {2016},
url = {http://arxiv.org/abs/1609.04747},
eprinttype = {arXiv},
eprint = {1609.04747},
timestamp = {Mon, 13 Aug 2018 16:48:10 +0200},
biburl = {https://dblp.org/rec/journals/corr/Ruder16.bib},
bibsource = {dblp computer science bibliography, https://dblp.org}
}

摘要

梯度下降优化算法虽然越来越受欢迎,但经常被用作黑盒优化器,因为很难获得对其优缺点的实际解释。本文旨在为读者提供有关不同算法的行为的直观信息,从而能够使用这些算法。在本概述的过程中,我们将查看梯度下降的不同变体,总结挑战,介绍最常见的优化算法,回顾并行和分布式环境中的体系结构,并研究优化梯度下降的其他策略。

1 引言

梯度下降法是最流行的优化算法之一,也是迄今为止最常用的优化神经网络的方法。同时,每个最先进的深度学习库包含各种算法的实现,以优化梯度下降(例如lasagne、caffe、keras的文档)。然而,这些算法经常被用作黑盒优化器,因为很难找到对它们优缺点的实际解释。
本文旨在为读者提供关于优化梯度下降的不同算法的行为的直觉,这将帮助使用它们。在第二节中,我们首先要看看梯度下降的不同变体。然后,我们将在第3节简要总结训练过程中的挑战。随后,在第4节中,我们将介绍最常见的优化算法,展示它们解决这些挑战的动机,以及这如何引出它们的更新规则。随后,在第5节中,我们将简要介绍在并行和分布式设置中优化梯度下降的算法和架构。最后,我们将在第6节中考虑有助于优化梯度下降的其他策略。
梯度下降是将目标函数 J ( θ ) J(\theta) J(θ) 最小的一种方法,通过目标函数的梯度 ∇ θ J ( θ ) \nabla_{\theta} J(\theta) θJ(θ) 更新模型参数 θ ∈ R d \theta \in \mathbb{R}^{d} θRd 。学习率 η \eta η 决定了我们达到(局部)最小值所采取的步骤的大小。换句话说,我们沿着目标函数产生的曲面坡度的方向下坡,直到我们到达山谷。

2 梯度下降及变体

梯度下降有三种变体,不同的是我们使用多少数据来计算目标函数的梯度。根据数据量的不同,我们在参数更新的准确性和执行更新所需的时间之间进行权衡。

2.1 批处理梯度下降(BGD)

传统梯度下降法,又称批梯度下降法,对整个训练数据集的参数θ计算代价函数的梯度:
θ = θ − η ⋅ ∇ θ J ( θ ) \theta=\theta-\eta \cdot \nabla_{\theta} J(\theta) θ=θηθJ(θ)
由于我们需要计算整个数据集的梯度来执行一次更新,批处理梯度下降可能非常缓慢,对于内存中不能容纳的数据集来说很难处理。批处理梯度下降也不允许我们在线更新我们的模型,即使用动态的新例子。
在代码中,批量梯度下降看起来像这样:

for i in range (nb_epochs):
	params_grad = evaluate_gradient(loss_function, data ,params)
	params = params - learning_rate * params_grad

对于预先定义的训练周期数,我们首先用我们的参数矢量计算整个数据集损失函数的梯度向量。请注意,最先进的深度学习库提供自动区分,有效地计算梯度.一些参数。如果你自己推导梯度,那么梯度检查是个好主意。
然后,我们根据梯度的方向更新参数,学习速率决定我们执行更新的大小。对于凸误差曲面,批量梯度下降算法保证收敛到全局最小值,对于非凸误差曲面,保证收敛到局部最小值。

2.2 随机梯度下降法(SGD)

随机梯度下降(SGD)则对训练示例 x ( i ) x^{(i)} x(i)和标签 y ( i ) y^{(i)} y(i)进行参数更新:
θ = θ − η ⋅ ∇ θ J ( θ ; x ( i ) ; y ( i ) ) \theta=\theta-\eta \cdot \nabla_{\theta} J\left(\theta ; x^{(i)} ; y^{(i)}\right) θ=θηθJ(θ;x(i);y(i))
批量梯度下降(BGD)对大型数据集执行冗余计算,因为它在每次参数更新之前重新计算类似示例的梯度。随机梯度下降法(SGD)通过一次执行一个更新来消除这种冗余。因此,它通常更快,也可以用于在线学习。SGD执行频繁的更新,其方差很高,导致目标函数剧烈波动,如图1所示。
图1:SGD波动
当批量梯度下降收敛到参数所在盆地的最小值时,SGD的波动一方面使它能够跳到新的、可能更好的局部最小值。另一方面,这最终使收敛到精确的最小值复杂化,因为SGD将继续超调。然而,当我们缓慢地降低学习率时,SGD表现出与批量梯度下降相同的收敛行为,对于非凸优化和凸优化,几乎可以确定分别收敛到局部或全局最小值。它的代码片段只是在训练示例上添加了一个循环,并对每个示例计算梯度。注意,我们在每个epoch都打乱训练数据,如6.1节所述。

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

2.3 小批量梯度下降(Mini-batch GD)

小批量梯度下降充分利用这两个方面的优势,并对每个小批量的 n n n 个训练样本进行更新:
θ = θ − η ⋅ ∇ θ J ( θ ; x ( i : i + n ) ; y ( i : i + n ) ) \theta=\theta-\eta \cdot \nabla_{\theta} J\left(\theta ; x^{(i: i+n)} ; y^{(i: i+n)}\right) θ=θηθJ(θ;x(i:i+n);y(i:i+n))
这样一来,减少了参数更新的方差,使得收敛更加稳定;并且可以利用最先进的深度学习库中常见的高度优化的矩阵优化,使计算小批量的梯度非常高效。通常mini-batch大小在50到256之间,但可以根据不同的应用而有所不同。小批量梯度下降法是神经网络训练的典型选择算法,在使用小批量梯度下降法时,通常也使用SGD。注意:为简单起见,在本文其余部分的SGD修改中,我们省略了参数 x ( i : i + n ) ; y ( i : i + n ) x^{(i: i+n)};y^{(i:i+n)} x(i:i+n);y(ii+n)
在代码中,我们现在不是迭代样本,而是迭代大小为50的 mini-batches:

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_grad

3 挑战

然而,传统小批量梯度下降并不保证良好的收敛,因此存在一些需要解决的挑战:

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

4 梯度下降优化算法

4.1 动量

SGD在沟谷中前进有困难,即在一个维度的表面曲线比另一个维度更陡峭的区域,这在局部最优附近是常见的。在这些情况下,SGD在沟谷的斜坡上振荡,而只在底部朝着局部最优方向犹豫不决地前进,如图2a所示。
图2
动量是一种帮助SGD在相关方向加速并抑制振荡的方法,如图2b所示。它通过将过去时间步长的更新向量的分数 γ γ γ 添加到当前更新向量来实现这一点。
v t = γ v t − 1 + η ∇ θ J ( θ ) θ = θ − v t \begin{aligned} v_{t} &=\gamma v_{t-1}+\eta \nabla_{\theta} J(\theta) \\ \theta &=\theta-v_{t} \end{aligned} vtθ=γvt1+ηθJ(θ)=θvt
动量项 γ γ γ 通常设置为0.9值或类似值。
本质上,当我们使用动量时,就像我们把球推下山。当球滚下坡时,它的动量越来越大,在路上变得越来越快(如果有空气阻力,即γ <1,它就会达到最终速度)。我们的参数更新也会发生同样的事情:对于梯度指向相同方向的维度,动量项会增加,而对于梯度改变方向的维度,动量项会减少。最终,我们得到了更快的收敛和更少的振荡。

4.2 Nesterov加速梯度(NAG)

然而,一个球从山上滚下来,盲目地跟着斜坡走,是非常不令人满意的。我们希望有一个更聪明的球,一个知道它要去哪里的球,这样它就知道在山坡再次倾斜之前减速。
Nesterov加速梯度(NAG)是一种让动量项具有这种预见性的方法。我们知道我们将使用动量项 γ v t − 1 \gamma v_{t-1} γvt1 来移动参数 θ \theta θ 。因此,计算 θ − γ v t − 1 \theta-\gamma v_{t-1} θγvt1 为我们提供了下一个参数位置的近似值(完全更新时缺少梯度),这是我们参数的大致位置。我们现在可以通过计算梯度的,不是当前参数 θ \theta θ ,而是参数的近似未来位置,来有效地向前看:
v t = γ v t − 1 + η ∇ θ J ( θ − γ v t − 1 ) θ = θ − v t \begin{aligned} v_{t} &=\gamma v_{t-1}+\eta \nabla_{\theta} J\left(\theta-\gamma v_{t-1}\right) \\ \theta &=\theta-v_{t} \end{aligned} vtθ=γvt1+ηθJ(θγvt1)=θvt
图3:Nesterov更新
我们再次将动量项 γ \gamma γ 的值设为0.9左右。动量首先计算当前梯度(图3中的蓝色小矢量),然后在更新的累积梯度(蓝色大矢量)的方向上进行大跳跃,而NAG首先在先前累积梯度(棕色矢量)的方向上进行大跳跃,测量梯度,然后进行校正(绿色矢量)。此预期更新可防止我们进行得太快,从而提高响应能力,从而显著提高RNN在许多任务上的性能。
现在我们能够将更新调整到误差函数的斜率并依次加速SGD,我们还希望将更新调整到每个单独的参数,根据它们的重要性执行更大或更小的更新。

4.3 自适应梯度(Adagrad)

Adagrad是一种基于梯度的优化算法,它的做法是:根据参数调整学习率,对不频繁更新的参数执行较大的学习率,对频繁更新的参数执行较小的学习率。因此,它非常适合处理稀疏数据。Dean等人发现Adagrad极大地提高了SGD的稳健性,并将其用于训练谷歌的大规模神经网络,这些神经网络在Youtube视频中学会了识别猫。此外,Pennington等人使用Adagrad来训练GloVe单词的嵌入,因为不频繁更新的单词比频繁更新的单词需要更大的更新。
之前,我们一次对所有参数 θ \theta θ 进行了更新,因为每个参数 θ i \theta_{i} θi 使用相同的学习速率 η η η 。由于Adagrad在每个时间点 t t t 对每个参数 θ i \theta_{i} θi 使用不同的学习率,因此我们首先显示Adagrad的每个参数的更新,然后将其向量化。为简明起见,我们将 g t , i g_{t, i} gt,i 设置为目标函数在时间步长t处对参数 θ i \theta_{i} θi 的梯度:
g t , i = ∇ θ t J ( θ t , i ) g_{t, i}=\nabla_{\theta_{t}} J\left(\theta_{t, i}\right) gt,i=θtJ(θt,i)
然后,每个时间步骤 t t t 处的每个参数 θ i \theta_{i} θi 的SGD更新变为:
θ t + 1 , i = θ t , i − η ⋅ g t , i \theta_{t+1, i}=\theta_{t, i}-\eta \cdot g_{t, i} θt+1,i=θt,iηgt,i
在其更新规则中,Adagrad根据 θ i \theta_{i} θi 过去计算的梯度,修改了每个参数 θ i \theta_{i} θi 在每个时间步长t处的一般学习率 η η η
θ t + 1 , i = θ t , i − η G t , i i + ϵ ⋅ g t , i \theta_{t+1, i}=\theta_{t, i}-\frac{\eta}{\sqrt{G_{t, i i}+\epsilon}} \cdot g_{t, i} θt+1,i=θt,iGt,ii+ϵ ηgt,i
G t ∈ R d × d G_{t} \in \mathbb{R}^{d \times d} GtRd×d是一个对角矩阵,每个对角元素 i , i i, i i,i θ i \theta_{i} θi 到时间步长 t t t 的梯度的平方和,而 ϵ \epsilon ϵ 是一个平滑项,为避免被零除(通常在 1 e − 8 1 e-8 1e8 的数量级)。有趣的是,如果没有平方根运算,算法的性能会差很多。
由于 G t G_{t} Gt 包含所有参数 θ θ θ 沿其对角线的过去梯度的平方和,我们现在可以通过在 G t G_{t} Gt g t g_{t} gt 之间执行一个按元素排列的矩阵向量乘以d来对我们的实现进行矢量化:
由于 G t G_{t} Gt 包含沿其对角线的所有参数 θ θ θ 的过去梯度的平方和,因此我们现在可以通过在 G t G_{t} Gt g t g_{t} gt 之间执行按元素的矩阵向量乘法 ⊙ \odot 来向量化我们的实现:
θ t + 1 = θ t − η G t + ϵ ⊙ g t \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{G_{t}+\epsilon}} \odot g_{t} θt+1=θtGt+ϵ ηgt
Adagrad的主要优点之一是它消除了手动调整学习率的需要。大多数实现使用默认值0.01并保持不变。
Adagrad的主要弱点是它在分母中积累了平方梯度:由于每增加一项都是正数,累积的和在训练过程中不断增长。这反过来会导致学习率缩小,最终变得非常小,在这一点上,算法不再能够获得额外的知识。以下算法旨在解决此缺陷。

4.4 自适应学习率(Adadelta)

Adadelta是Adagrad的扩展,旨在降低其积极,单调降低的学习速度。Adadelta不是累积所有过去的平方梯度,而是将累积的过去梯度的窗口限制为某个固定大小的 w w w
梯度之和被递归地定义为所有过去平方梯度的衰减平均值,而不是低效地存储 w w w 个先前平方梯度。然后,时间步长 t t t 处的运行平均值 E [ g 2 ] t E\left[g^{2}\right]_{t} E[g2]t 仅取决于先前平均值和当前梯度(作为与动量项相似的分数 γ γ γ):
E [ g 2 ] t = γ E [ g 2 ] t − 1 + ( 1 − γ ) g t 2 E\left[g^{2}\right]_{t}=\gamma E\left[g^{2}\right]_{t-1}+(1-\gamma) g_{t}^{2} E[g2]t=γE[g2]t1+(1γ)gt2
我们将 γ γ γ 设置为与动量项类似的值,约为0.9。为清楚起见,我们现在根据参数更新向量 Δ θ t \Delta \theta_{t} Δθt 重写我们的传统更新:
Δ θ t = − η ⋅ g t , i θ t + 1 = θ t + Δ θ t \begin{aligned} \Delta \theta_{t} &=-\eta \cdot g_{t, i} \\ \theta_{t+1} &=\theta_{t}+\Delta \theta_{t} \end{aligned} Δθtθt+1=ηgt,i=θt+Δθt
因此,我们先前导出的Adagrad参数更新向量采用以下形式:
Δ θ t = − η G t + ϵ ⊙ g t \Delta \theta_{t}=-\frac{\eta}{\sqrt{G_{t}+\epsilon}} \odot g_{t} Δθt=Gt+ϵ ηgt
我们现在简单地将对角矩阵 G t G_{t} Gt 替换为过去平方梯度上衰减的平均值 E [ g 2 ] t E\left[g^{2}\right]_{t} E[g2]t
Δ θ t = − η E [ g 2 ] t + ϵ g t \Delta \theta_{t}=-\frac{\eta}{\sqrt{E\left[g^{2}\right]_{t}+\epsilon}} g_{t} Δθt=E[g2]t+ϵ ηgt
因为分母就是梯度的均方根(RMS)误差标准,所以我们可以用简写的标准来代替它:
Δ θ t = − η R M S [ g ] t g t \Delta \theta_{t}=-\frac{\eta}{R M S[g]_{t}} g_{t} Δθt=RMS[g]tηgt
作者指出,本次更新中的单位(以及SGD、Momentum或Adagrad中的单位)不匹配,即更新应具有与参数相同的假设单位。为了实现这一点,他们首先定义另一个指数衰减平均值,这次不是平方梯度,而是平方参数更新:
E [ Δ θ 2 ] t = γ E [ Δ θ 2 ] t − 1 + ( 1 − γ ) Δ θ t 2 E\left[\Delta \theta^{2}\right]_{t}=\gamma E\left[\Delta \theta^{2}\right]_{t-1}+(1-\gamma) \Delta \theta_{t}^{2} E[Δθ2]t=γE[Δθ2]t1+(1γ)Δθt2
因此,参数更新的均方根误差为:
R M S [ Δ θ ] t = E [ Δ θ 2 ] t + ϵ R M S[\Delta \theta]_{t}=\sqrt{E\left[\Delta \theta^{2}\right]_{t}+\epsilon} RMS[Δθ]t=E[Δθ2]t+ϵ
由于 R M S [ Δ θ ] t R M S[\Delta \theta]_{t} RMS[Δθ]t 值是未知的,我们用上一个时间步长的参数更新的RMS来近似它。将先前更新规则中的学习率 η η η 替换为 R M S [ Δ θ ] t − 1 R M S[\Delta \theta]_{t-1} RMS[Δθ]t1 ,最终生成Adadelta更新规则:
Δ θ t = − R M S [ Δ θ ] t − 1 R M S [ g ] t g t θ t + 1 = θ t + Δ θ t \begin{aligned} &\Delta \theta_{t}=-\frac{R M S[\Delta \theta]_{t-1}}{R M S[g]_{t}} g_{t} \\ &\theta_{t+1}=\theta_{t}+\Delta \theta_{t} \end{aligned} Δθt=RMS[g]tRMS[Δθ]t1gtθt+1=θt+Δθt
使用Adadelta,我们甚至不需要设置默认学习速率,因为它已从更新规则中删除。

4.5 RMSprop

RMSprop是Geoff Hinton在他的Coursera课程的第6e节课中提出的一种未发表的自适应学习率方法。
RMSprop和Adadelta几乎都是在同一时间独立开发的,这源于解决Adagrad学习率急剧下降的需要。RMSprop实际上与我们上面推导的Adadelta的第一个更新向量相同:
E [ g 2 ] t = 0.9 E [ g 2 ] t − 1 + 0.1 g t 2 θ t + 1 = θ t − η E [ g 2 ] t + ϵ g t \begin{aligned} E\left[g^{2}\right]_{t} &=0.9 E\left[g^{2}\right]_{t-1}+0.1 g_{t}^{2} \\ \theta_{t+1} &=\theta_{t}-\frac{\eta}{\sqrt{E\left[g^{2}\right]_{t}+\epsilon}} g_{t} \end{aligned} E[g2]tθt+1=0.9E[g2]t1+0.1gt2=θtE[g2]t+ϵ ηgt
RMSprop还将学习速率除以平方梯度的指数衰减平均值。Hinton建议将 γ γ γ 设置为0.9,而学习率 η η η 的良好默认值为0.1。

4.6 Adam

自适应矩估计(Adam)是另一种计算每个参数的自适应学习率的方法。除了像Adadelta和RMSprop一样存储过去平方梯度的指数衰减平均值 v t v_{t} vt 之外,Adam还保持过去梯度的指数衰减平均值 m t m_{t} mt ,类似于动量:
m t = β 1 m t − 1 + ( 1 − β 1 ) g t v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 \begin{aligned} m_{t} &=\beta_{1} m_{t-1}+\left(1-\beta_{1}\right) g_{t} \\ v_{t} &=\beta_{2} v_{t-1}+\left(1-\beta_{2}\right) g_{t}^{2} \end{aligned} mtvt=β1mt1+(1β1)gt=β2vt1+(1β2)gt2
m t m_{t} mt v t v_{t} vt 分别是梯度的第一矩(平均值)和第二矩(非中心方差)的估计值,因此该方法的名称。 m t m_{t} mt v t v_{t} vt 被初始化为零向量,Adam的作者观察到它们偏向于零,特别是在初始时间步长期间,尤其是当衰减率很小时(即 β 1 \beta_{1} β1 β 2 \beta_{2} β2 接近于1)。
他们通过计算经过偏差校正的一阶矩和二阶矩估计来抵消这些偏差:
m ^ t = m t 1 − ( β 1 ) t v ^ t = v t 1 − ( β 2 ) t \begin{aligned} \hat{m}_{t} &=\frac{m_{t}}{1-(\beta_{1})^{t}} \\ \hat{v}_{t} &=\frac{v_{t}}{1-(\beta_{2})^{t}} \end{aligned} m^tv^t=1(β1)tmt=1(β2)tvt
然后,它们使用这些参数来更新参数,就像我们在Adadelta和RMSprop中看到的那样,因此Adam的更新规则为:
θ t + 1 = θ t − η v ^ t + ϵ m ^ t \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{\hat{v}_{t}}+\epsilon} \hat{m}_{t} θt+1=θtv^t +ϵηm^t
作者建议 β 1 \beta_{1} β1 的默认值为0.9, β 2 \beta_{2} β2 的默认值为0.999, ϵ \epsilon ϵ 的默认值为 1 0 − 8 10^{-8} 108 。他们的经验表明,Adam在实践中运行良好,并优于其他自适应学习方法算法。

4.7 AdaMax

Adam更新规则中的 v t v_{t} vt 因子与过去梯度(通过 v t − 1 v_{t-1} vt1 项)的 ℓ 2 \ell_{2} 2 范数和当前梯度 ∣ g t ∣ 2 \left|g_{t}\right|^{2} gt2 成反比缩放梯度:
v t = β 2 v t − 1 + ( 1 − β 2 ) ∣ g t ∣ 2 v_{t}=\beta_{2} v_{t-1}+\left(1-\beta_{2}\right)\left|g_{t}\right|^{2} vt=β2vt1+(1β2)gt2
我们可以将这个更新推广到 ℓ 2 \ell_{2} 2 范数。注意,Kingma和Ba也将 β 2 \beta_{2} β2 参数化为 β 2 p \beta_{2}^{p} β2p:
v t = β 2 p v t − 1 + ( 1 − β 2 p ) ∣ g t ∣ p v_{t}=\beta_{2}^{p} v_{t-1}+\left(1-\beta_{2}^{p}\right)\left|g_{t}\right|^{p} vt=β2pvt1+(1β2p)gtp
p p p 值的范数通常在数值上变得不稳定,这就是为什么 ℓ 1 \ell_{1} 1 ℓ 2 \ell_{2} 2 范数在实践中最常见的原因。然而, ℓ ∞ \ell_{\infty} 通常也表现出稳定的行为。为此,作者提出了AdaMax,并证明了具有 ℓ ∞ \ell_{\infty} v t v_{t} vt 收敛到以下更稳定的值。为了避免与Adam混淆,我们用 u t u_{t} ut 表示无穷范数约束的 v t v_{t} vt
u t = β 2 ∞ v t − 1 + ( 1 − β 2 ∞ ) ∣ g t ∣ ∞ = max ⁡ ( β 2 ⋅ v t − 1 , ∣ g t ∣ ) \begin{aligned} u_{t} &=\beta_{2}^{\infty} v_{t-1}+\left(1-\beta_{2}^{\infty}\right)\left|g_{t}\right|^{\infty} \\ &=\max \left(\beta_{2} \cdot v_{t-1},\left|g_{t}\right|\right) \end{aligned} ut=β2vt1+(1β2)gt=max(β2vt1,gt)
现在,我们可以通过将Adam更新公式中的 v ^ t + ϵ \sqrt{\hat{v}_{t}}+\epsilon v^t +ϵ 替换为 u t u_{t} ut 来获得Adamax更新规则:
θ t + 1 = θ t − η u t m ^ t \theta_{t+1}=\theta_{t}-\frac{\eta}{u_{t}} \hat{m}_{t} θt+1=θtutηm^t
请注意,由于 u t u_{t} ut 依赖于 m a x max max 运算,因此不可能像Adam中的 m t m_{t} mt v t v_{t} vt 那样偏向零,这就是为什么我们不需要计算 u t u_{t} ut 的偏差校正。优化默认值是 η = 0.002 \eta=0.002 η=0.002 β 1 = 0.9 \beta_{1}=0.9 β1=0.9 β 2 = 0.999 \beta_{2}=0.999 β2=0.999

4.8 Nadam

正如我们之前看到的,Adam可以被视为RMSprop和动量的组合:RMSprop贡献了过去平方梯度 v t v_{t} vt 的指数衰减平均值,而动量则解释了过去梯度 m t m_{t} mt 的指数衰减平均值。我们还看到Nesterov加速梯度(NAG)优于传统动量方法。
Nadam(Nesterov加速自适应矩估计)则结合了Adam和NAG。为了把NAG纳入Adam,我们需要修改它的动量项 m t m_{t} mt
首先,让我们回顾一下使用当前符号的动量更新规则:
g t = ∇ θ t J ( θ t ) m t = γ m t − 1 + η g t θ t + 1 = θ t − m t \begin{aligned} g_{t} &=\nabla_{\theta_{t}} J\left(\theta_{t}\right) \\ m_{t} &=\gamma m_{t-1}+\eta g_{t} \\ \theta_{t+1} &=\theta_{t}-m_{t} \end{aligned} gtmtθt+1=θtJ(θt)=γmt1+ηgt=θtmt
其中 J J J 是我们的目标函数, γ \gamma γ 是动量衰减项, η \eta η 是我们的步长。将上面的第三个等式展开,可以得到:
θ t + 1 = θ t − ( γ m t − 1 + η g t ) \theta_{t+1}=\theta_{t}-\left(\gamma m_{t-1}+\eta g_{t}\right) θt+1=θt(γmt1+ηgt)
这再次证明了动量包括沿着先前动量矢量的方向和沿着当前梯度的方向走一步。
然后,NAG允许我们在计算梯度之前用动量步长更新参数,从而在梯度方向上执行更精确的一步。因此,我们只需修改梯度 g t g_{t} gt 即可达到NAG:
g t = ∇ θ t J ( θ t − γ m t − 1 ) m t = γ m t − 1 + η g t θ t + 1 = θ t − m t \begin{aligned} g_{t} &=\nabla_{\theta_{t}} J\left(\theta_{t}-\gamma m_{t-1}\right) \\ m_{t} &=\gamma m_{t-1}+\eta g_{t} \\ \theta_{t+1} &=\theta_{t}-m_{t} \end{aligned} gtmtθt+1=θtJ(θtγmt1)=γmt1+ηgt=θtmt
Dozat建议通过以下方式修改NAG:不是应用动量步骤两次(第一次更新梯度 g t g_{t} gt ,第二次更新参数 θ t + 1 \theta_{t+1} θt+1 )。我们现在直接应用前瞻动量矢量来更新当前参数:
g t = ∇ θ t J ( θ t ) m t = γ m t − 1 + η g t θ t + 1 = θ t − ( γ m t + η g t ) \begin{aligned} g_{t} &=\nabla_{\theta_{t}} J\left(\theta_{t}\right) \\ m_{t} &=\gamma m_{t-1}+\eta g_{t} \\ \theta_{t+1} &=\theta_{t}-\left(\gamma m_{t}+\eta g_{t}\right) \end{aligned} gtmtθt+1=θtJ(θt)=γmt1+ηgt=θt(γmt+ηgt)
我们现在使用当前的动量向量 m t m_{t} mt 来展望未来,而不是像上面那样使用先前的动量向量 m t − 1 m_{t-1} mt1 。为了将Nesterov动量添加到Adam中,我们同样可以用现在的动量矢量代替以前的动量矢量。首先,回想一下Adam更新规则如下(注意,我们不需要修改 v ^ t \hat{v}_{t} v^t ):
m t = β 1 m t − 1 + ( 1 − β 1 ) g t m ^ t = m t 1 − β 1 t θ t + 1 = θ t − η v ^ t + ϵ m ^ t \begin{aligned} m_{t} &=\beta_{1} m_{t-1}+\left(1-\beta_{1}\right) g_{t} \\ \hat{m}_{t} &=\frac{m_{t}}{1-\beta_{1}^{t}} \\ \theta_{t+1} &=\theta_{t}-\frac{\eta}{\sqrt{\hat{v}_{t}}+\epsilon} \hat{m}_{t} \end{aligned} mtm^tθt+1=β1mt1+(1β1)gt=1β1tmt=θtv^t +ϵηm^t
v ^ t \hat{v}_{t} v^t v t v_{t} vt 的定义展开第二个方程,我们可以得到:
θ t + 1 = θ t − η v ^ t + ϵ ( β 1 m t − 1 1 − β 1 t + ( 1 − β 1 ) g t 1 − β 1 t ) \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{\hat{v}_{t}}+\epsilon}\left(\frac{\beta_{1} m_{t-1}}{1-\beta_{1}^{t}}+\frac{\left(1-\beta_{1}\right) g_{t}}{1-\beta_{1}^{t}}\right) θt+1=θtv^t +ϵη(1β1tβ1mt1+1β1t(1β1)gt)
请注意, β 1 m t − 1 1 − β 1 t \frac{\beta_{1} m_{t-1}}{1-\beta_{1}^{t}} 1β1tβ1mt1 只是对前一个时间步的动量矢量的偏差校正估计。因此,我们可以将其替换为 m ^ t − 1 \hat{m}_{t-1} m^t1
θ t + 1 = θ t − η v ^ t + ϵ ( β 1 m ^ t − 1 + ( 1 − β 1 ) g t 1 − β 1 t ) \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{\hat{v}_{t}}+\epsilon}\left(\beta_{1} \hat{m}_{t-1}+\frac{\left(1-\beta_{1}\right) g_{t}}{1-\beta_{1}^{t}}\right) θt+1=θtv^t +ϵη(β1m^t1+1β1t(1β1)gt)
这个方程看起来非常类似于之前的扩展动量项。我们现在可以添加Nesterov动量,只需用当前动量向量 m ^ t \hat{m}_{t} m^t 的偏差修正估计替换上一时间步 m ^ t − 1 \hat{m}_{t-1} m^t1 动量向量的偏差修正估计,这就有了Nadam更新规则:
θ t + 1 = θ t − η v ^ t + ϵ ( β 1 m ^ t + ( 1 − β 1 ) g t 1 − β 1 t ) \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{\hat{v}_{t}}+\epsilon}\left(\beta_{1} \hat{m}_{t}+\frac{\left(1-\beta_{1}\right) g_{t}}{1-\beta_{1}^{t}}\right) θt+1=θtv^t +ϵη(β1m^t+1β1t(1β1)gt)

4.9 算法可视化

以下两幅图提供了对所提出的优化算法的优化行为的一些直觉。
在图4a中,我们看到他们在损失面(Beale函数)的轮廓上所采取的路径。所有人都从同一点出发,通过不同的路径到达最小值。注意,Adagrad、Adadelta和RMSprop立刻朝正确的方向出发,并以同样快的速度会合,而Momentum和NAG则被带离轨道,让人想起一个球从山上滚下来的画面。然而,NAG能够更快地纠正它的路线,因为它增加了对前方的反应,并朝着最小的方向前进。
图4b显示了算法在鞍点的行为,即一个维度的斜率为正,而另一个维度的斜率为负,这对SGD来说是一个难点。注意这里发现SGD、Momentum和NAG很难逃离鞍点,尽管后两个最终设法逃离了鞍点,但是Adagrad、RMSprop和Adadelta能迅速向下,而Adadelta跑在最前面。
图4a
图4b
可以看出,Adagrad、Adadelta、RMSprop、Adam等自适应学习率方法是最适合这些场景的,收敛性最好。

4.10 使用哪个优化器?

那么,您应该使用哪个优化器呢?如果您的输入数据是稀疏的,那么您可能会使用一种自适应学习速率方法来获得最佳结果。另一个好处是,您不需要调整学习速率,使用默认值可能会获得最佳结果。
总之,RMSprop是Adagrad的扩展,它可以处理急剧下降的学习率。它与Adadelta相同,只是Adadelta在分子更新规则中使用了参数更新的RMS。最后,Adam在RMSprop中添加了偏差校正和动量。到目前为止,RMSprop, Adadelta和Adam是非常相似的算法,在类似的情况下也能做得很好。Kingma等人表明,随着梯度变得稀疏,其偏差校正帮助Adam在优化的最后略优于RMSprop。到目前为止,Adam可能是最好的选择。
有趣的是,许多最近的论文使用了没有动量的传统SGD和简单的学习率退火计划。如前所述,SGD通常能够找到最小值,但它可能比一些优化器花费更长的时间,更依赖于健壮的初始化和退火调度,并且可能会卡在鞍点而不是局部最小值上。因此,如果你关心快速收敛和训练一个深度或复杂的神经网络,你应该选择一种自适应学习率方法。

5 SGD的并行化和分布化

考虑到大规模数据解决方案的无处不在和低商品集群的可用性,分发SGD以进一步加速是一个显而易见的选择。SGD本身就是一个内在的顺序:一步一步地,我们朝着最小的方向前进。运行它可以提供良好的收敛,但可能会很慢,尤其是在大型数据集上。相比之下,异步运行SGD速度更快,但工作人员之间的通信不佳可能会导致收敛较差。此外,我们还可以在一台机器上并行SGD,而不需要大型计算集群。以下是已提出的用于优化并行和分布式SGD的算法和体系结构。

5.1 HogWild!

Niu等人引入了一个名为Hogwild的更新方案,允许在cpu上并行执行SGD更新。处理器可以在不锁定参数的情况下访问共享内存。这只在输入数据稀疏的情况下有效,因为每次更新只会修改所有参数的一部分。它们表明,在这种情况下,更新方案几乎达到了最优的收敛速度,因为处理器不太可能重写有用的信息。

5.2 Downpour SGD

Downpour SGD是SGD的异步变体,Dean等人在谷歌的DistBelief框架(TensorFlow的前身)中使用了SGD。它在训练数据的子集上并行地运行模型的多个副本。这些模型将它们的更新发送到一个参数服务器,该服务器被分散在许多机器上。每台机器负责存储和更新模型参数的一部分。然而,由于副本之间不相互通信,例如通过共享权重或更新,它们的参数不断面临发散的风险,阻碍了收敛。

5.3 SGD容延迟算法

McMahan和Streeter将AdaGrad扩展到并行设置,他们开发了延迟容忍算法,不仅可以适应过去的梯度,还可以适应更新延迟。实践证明,这是行之有效的。

5.4 TensorFlow

TensorFlow是谷歌最近推出的开源框架,用于大规模机器学习模型的实现和部署。它是基于他们使用DistBelief的经验,并且已经在内部用于在大范围的移动设备和大规模分布式系统上执行计算。2016年4月发布的分布式版本依赖于一个计算图,该计算图被拆分为每个设备的子图,而通信使用发送/接收节点对进行。

5.5 弹性平均SGD

Zhang等人提出了弹性平均SGD(EASGD),它将异步SGD的工作参数与弹性力联系起来,即由参数服务器存储的中心变量。这允许局部变量从中心变量进一步波动,这在理论上允许更多地探索参数空间。他们的经验表明,这种增加的勘探能力通过发现新的局部最优解而提高了性能。

6 优化SGD的其他策略

最后,我们介绍了可以与前面提到的任何算法一起使用的其他策略,以进一步提高SGD的性能。

6.1 Shuffling和Curriculum Learning

通常,我们希望避免以有意义的顺序为模型提供训练示例,因为这可能会使优化算法产生偏差。因此,在每个epoch之后对训练数据进行Shuffling通常是一个好主意。
另一方面,在某些情况下,我们的目标是逐步解决更困难的问题,以有意义的顺序提供训练样本实际上可能会提高性能和更好的收敛。建立这种有意义的顺序的方法称为Curriculum Learning。

6.2 批量规范化

为了便于学习,我们通常用零均值和单位方差来初始化参数的初值。随着训练的进行和参数的不同程度的更新,我们失去了这种标准化,这减慢了训练,并随着网络变得更深而放大了变化。
批量规范化为每个小批重新建立这些规范化,并且更改也通过操作向后传播。通过将规范化作为模型体系结构的一部分,我们可以使用更高的学习率,而对初始化参数的关注更少。批处理规范化还起到了规范器的作用,减少了(时甚至消除了)Dropout的需要。

6.3 提前停止

Geoff Hinton说:“早点停下来是一顿美丽的免费午餐。”因此,您应该在培训期间始终监视验证集上的错误,如果验证错误没有得到足够的改善,则应停止(耐心等待)。

6.4 梯度噪声

Neelakantan等人向每个梯度更新添加遵循高斯分布 N ( 0 , σ t 2 ) N\left(0, \sigma_{t}^{2}\right) N(0,σt2) 的噪声:
g t , i = g t , i + N ( 0 , σ t 2 ) g_{t, i}=g_{t, i}+N\left(0, \sigma_{t}^{2}\right) gt,i=gt,i+N(0,σt2)
他们根据以下计划对差异进行退火:
σ t 2 = η ( 1 + t ) γ \sigma_{t}^{2}=\frac{\eta}{(1+t)^{\gamma}} σt2=(1+t)γη
他们表明,添加这种噪声可以使网络对较差的初始化更加健壮,并有助于训练特别深入和复杂的网络。他们怀疑,增加的噪声使模型有更多的机会逃脱并找到新的局部极小值,而对于较深的模型,这种情况更为频繁。

7 总结

在本文中,我们初步研究了梯度下降的三种变体,其中最流行的是小批量梯度下降。然后,我们研究了优化SGD最常用的算法:动量法、Nesterov加速梯度法、Adagrad法、Adadelta法、RMSprop法、Adam法、AdaMax法、Nadam法,以及优化异步SGD的不同算法。最后,我们考虑了其他改善SGD的策略,如Shuffling和Curriculum Learning、批量规范化和提前停止。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值