优化器算法与技术
概述
”优化器“这一概念相信对于CVer、NLPer们并不陌生,是当今神经网络模型训练时的必备部件,几乎所有的深度学习算法研究、执行都会涉及到优化器的改良或使用。在深度学习中有两个重要概念:1、损失函数,即模型能力与参考值的差异,是一种评价指标;2、优化函数,是根据损失的反向梯度所产生的优化策略,以约束模型迭代到最优解。
优化器在机器学习、深度学习优化中扮演十分重要的角色,同样的模型结构、数据和loss函数,使用不同的优化器也有可能带来迥异的效果,甚至会造成梯度爆炸等问题。所以了解各种优化器的基本原理对于更好、更快地训练模型非常重要,本文我们探讨下各种不同的优化器及其性能。
经典算法
基于梯度下降的方法
BGD
BGD(批量梯度下降,Batch Gradient Descent)是最基本的梯度下降算法,也是较早应用到训练任务中的。BGD的策略是:一次性将整个训练集送入模型中计算损失,求和并计算梯度,然后更新一次参数,再执行下一个epoch,直到结束。BGD的更新策略公式表达如下:
W
t
+
1
=
W
t
−
η
t
∑
i
=
1
n
∇
W
t
J
(
W
t
;
x
i
,
y
i
)
W_{t+1}=W_t - η_t\sum_{i=1}^{n}∇_{W_t}J(W_t; x_i, y_i )
Wt+1=Wt−ηti=1∑n∇WtJ(Wt;xi,yi)
BGD可以通俗理解为:下山时如果掌握了地势情况,则选择最快的下山路线。
优点:
- 由于BGD更新参数时采用了数量更大的样本,因此梯度方向与最优解方向更一致,参数更新也更平滑;
- BGD对全部样本只执行一次更新,因此总训练时间更短。
缺点:
- 由于计算时参与的样本量很大,因此对于单步的参数更新速度会很慢,且内存占用较大;
- 容易陷入局部最优值,导致算法提前结束;
- 不支持在线学习,即新增样本的场景。
SGD
相比BGD策略,随机梯度下降SGD(随机梯度下降,Stochastic Gradient Descent)则采取单样本更新的方式,即单条数据即可实现一次参数更新。“随机”是指每次选取的样本具备随机性,即开始一个epoch之前先将训练集打乱,再顺序读取样本并计算,适用于样本量过大的训练场景。公式如下:
W
t
+
1
=
W
t
−
η
t
∇
W
t
J
(
W
t
;
x
i
,
y
i
)
W_{t+1}=W_t - η_t∇_{W_t}J(W_t; x_i, y_i )
Wt+1=Wt−ηt∇WtJ(Wt;xi,yi)
图说明如下:
可以通俗理解为:一个盲人下山时,无法得知山底具体在什么方向,只能根据脚下情况朝最大坡度方向行进,虽然会经历一些曲折,但是总能下到山底。
优点:
- 由于一次选取一条样本迭代,计算量相比BGD要小得多,因此一次迭代时参数更新速度快,适用于样本量较大的情况;
- 支持在线学习的场景,对于新加入的样本可以随时更新。
缺点:
- 每个训练步的特征数量很少,造成参数更新不稳定,容易受到噪声或异常值的影响。每次迭代时更新方向未必准确,从而导致损失也跌宕起伏,但最终一般都能顺利收敛;
- 同样不能很好地改善局部陷入问题。
ASGD
随机平均梯度下降(Averaged Stochastic Gradient Descent,ASGD)在SGD的基础上增加历史参数的平均值度量,以确保参数收敛的稳定性,是SGD的牺牲空间以提高时间效率的策略版本。公式如下:
W
t
=
W
t
−
1
−
1
s
t
−
s
0
∑
n
=
s
0
s
t
η
n
∇
W
n
J
(
W
n
;
x
i
,
y
i
)
W_t=W_{t-1}-\frac {1}{s_t-s_0}\sum _{n=s_0}^{s_t}η_n∇_{W_n}J(W_n; x_i, y_i )
Wt=Wt−1−st−s01n=s0∑stηn∇WnJ(Wn;xi,yi)
可以看出相比SGD,ASGD计算过去t个时期的平均梯度,并用于当前更新。
MBGD
MBGD(小批量梯度下降, Mini-Batch Gradient Descent)可以认为是上述二者的折中方案,有效解决BGD执行时更新速度慢、以及SGD执行时参数收敛不稳定的问题。方法是每次迭代时选择小批量的数据计算并更新,即对于每个批量的样本应用BGD,公式如下(假设批量大小为
b
b
b):
W
t
+
1
=
W
t
−
η
t
∑
i
=
m
m
+
b
−
1
∇
W
t
J
(
W
t
;
x
i
,
y
i
)
W_{t+1}=W_t - η_t\sum_{i=m}^{m+b-1}∇_{W_t}J(W_t; x_i, y_i )
Wt+1=Wt−ηti=m∑m+b−1∇WtJ(Wt;xi,yi)
优点:
- 降低参数更新时的方差,模型收敛更加稳定。相对于SGD,由于参与更新的样本较多,参数更新也更平滑;相对于BGD,单次训练的参数更新速度也更快。
缺点:
- 局部最优值问题依然存在;
- 对学习率较为敏感,表现在学习率小容易造成收敛速度慢,学习率大又可能导致参数在最优点附近跳跃。
动量方法
动量的定义
从现在开始,介绍基于动量的优化方法,在开始之前引入一个重要概念—“泄漏平均值(Leaky Average)”,也称作指数加权平均,其基本计算方法如下:
v
t
=
β
v
t
−
1
+
g
t
,
t
−
1
v_t=\beta v_{t-1} + g_{t, t-1}
vt=βvt−1+gt,t−1
其中
β
∈
(
0
,
1
)
\beta\in(0,1)
β∈(0,1),上述公式用于计算多个历史梯度的“平均值”(实际为指数加权的累积和),
v
v
v被称为动量(Momentum),它代表了过去梯度的累积量。泄漏平均值的思想同样是减小更新时的参数方差,其效果要好于MBGD算法。
为了更清晰地展示动量原理,将上述公式展开,结果如下:
v
t
=
β
2
v
t
−
2
+
β
v
t
−
1
+
g
t
,
t
−
1
=
,
,
,
=
∑
β
τ
g
t
−
τ
,
t
−
τ
−
1
.
v_t=\beta^2v_{t-2} + \beta v_{t-1} + g_{t,t-1}=,,,=\sum {\beta^{\tau}g_{t-\tau,t-\tau-1}}.
vt=β2vt−2+βvt−1+gt,t−1=,,,=∑βτgt−τ,t−τ−1.
可以清晰看出,
β
\beta
β的取值大小决定了历史梯度的强度,较大时历史梯度占比较大,梯度均值的特征会更加明显;较小时当前步的梯度占比较大,效果变成了对当前梯度的修正。
因而动量法实则将参数更新趋向历史梯度加权平均值的方向,而不是像MBGD算法一样直接遗忘过去长期的梯度量。动量法靠累加操作使历史梯度得到保留,也免去了每次获得梯度时必须要反向传播一次的麻烦。
因此上述泄漏平均值的概念构成了一切基于动量优化的基础,动量的引入使得模型更新时收敛速度更快、且更不易陷入局部最优点。在物理学中,动量可以描述为一个小球从山坡上受重力作用向下滚动,虽然滚动的过程较为曲折,但是由于惯性原因,整个过程最快下降方向的力对它影响最大,因而总体下降趋势也与最快方向一致。优化器动量的提出也是通过累加 v v v以保留下降时的“惯性”,从而保证参数更新不会偏离太多。
下面我们逐一介绍基于动量思想设计的经典优化器方法。
Momentum动量法
有了动量的概念,动量优化法便产生了,通过累积下降速度、减少震荡,使参数更新的方向更稳定。算法实现时,每次执行梯度更新都会计入之前梯度方向的惯性,使梯度变化更加平滑,这点类似一阶马尔科夫假设,因而减少了震荡问题。动量法同样是通过计算梯度的指数加权平均数获得累积,并融入当前的梯度量,整体权重更新公式如下:
v
t
=
γ
v
t
−
1
+
η
∇
θ
t
−
1
J
(
θ
t
−
1
)
θ
t
=
θ
t
−
1
−
v
t
v_t=\gamma v_{t-1}+\eta ∇_{\theta_{t-1}} J(\theta_{t-1}) \\ \theta_t = \theta_{t-1} - v_t
vt=γvt−1+η∇θt−1J(θt−1)θt=θt−1−vt
其中
γ
\gamma
γ表示动量程度,通常取值0.9,动量法在优化时的效果图如下:
上图能够反映出,动量每次更新时由于携带了先前的惯性,因此更新方向相比一般SGD偏离度更小,模型收敛速度也会更快。为什么累积先前动量能够有效修正当前梯度的偏差,使优化方向更趋向于正确方向呢?笔者个人分析: 原因在于数据均匀分布时所带有的 “一般性” 特征,“一般性”特征是大多数样本所共有的,能够在多数数据中反映出来。如果一份训练数据是经随机打乱、分布均匀的,则数据中任意区域子集的特征也基本都是均匀的,能够反映整体数据的“一般性”,并体现在梯度变化中。因此累积先前动量能够融合历史数据的所有特征,由于“一般性”为数据普遍特性,因此它的梯度贡献在指数加权平均后还会表现较强,相对而言其它不重要的信息如噪声在数据中分布弥散,容易在计算后减弱。如此通过累积的指数加权平均方法使“一般性”梯度得到有效保留,模型优化的主方向也得以保持,参数更新自然也就稳定了。
总结动量的优点如下:
- 随机梯度的方法(累积的过程相当于引入噪声);
- 解决Hessian矩阵病态问题(即上面说的SGD在收敛过程中和正确梯度相比摆动较大的问题)。
接下来我们举个简单的例子,以证明动量法在减少波动、加速收敛方面的有效性(原讲解参考吴恩达《深度学习》视频课程)。
原问题描述:用散点图描绘伦敦一年的气温变化,横坐标代表日期,纵坐标为温度(°F)。则图绘制如下:
可以看出如果仅仅将温度值直接表示在散点图上,整体天气变化很不稳定。我们采取如下方法表示:每一天的温度表示
t
i
t_i
ti计算为
t
i
=
0.9
∗
t
i
−
1
+
0.1
∗
t
i
′
t_i=0.9*t_{i-1} + 0.1*t_i^{'}
ti=0.9∗ti−1+0.1∗ti′
其中
t
i
′
t_i^{'}
ti′为第
i
i
i天的实际温度,上述公式实则计算每日温度的指数加权平均,加权值
β
\beta
β设置为0.9,而当前量权重为
(
1
−
β
)
=
0.1
(1-\beta)=0.1
(1−β)=0.1. 使用
t
i
t_i
ti而不是
t
i
′
t_i^{'}
ti′绘制散点图效果如下图红色部分:
可以看出分布确实变得稳定了,我们尝试调整
β
\beta
β为0.98,则
(
1
−
β
)
(1-\beta)
(1−β)也相应变为0.02,使用新方法计算并绘图如下:
上图显示,绿色点相比红色点分布更加平滑,因为加权值的提升使历史温度在当前温度取值的占比更大,因而总体特性更加明显,温度变化也就更加稳定。用视频课里吴恩达老师的解释就是:当
β
\beta
β增大时,考虑的历史均值更多,因此对当前的温度变化会适应地更慢,应对变化的延迟也会更大。最后再来对比下三种不同的温度采样算法对趋势所带来的影响(黄线标示了蓝色散点即未使用平均的变化趋势),以便于深刻体会指数加权平均的作用,以及对应的动量法的意义。
缺点:
- 动量法也存在明显的缺点,即累积动量会造成下降速度一直保持高位,即便接近最优点时可能也难以减速,容易造成模型不收敛的问题。换言之,动量法缺乏对参数收敛状态的预判,不能及时停止。
动量法修正—牛顿法
Momentum算法相比各种梯度下降方法对模型的收敛性能更好,后续出现了对Momentum的改进,即牛顿动量梯度下降(Nesterov Accelerated Gradient ,NAG)。相比Momentum,牛顿法的改变在于计算梯度时加入了预期更新的动量,而Momentum只对当前参数状态计算梯度。公式描述如下:
v
t
=
β
v
t
−
1
+
∇
θ
J
(
θ
t
−
1
−
α
⋅
β
v
t
−
1
)
θ
t
=
θ
t
−
1
−
α
v
t
v_t=\beta v_{t-1}+∇_{\theta} J(\theta_{t-1}-\alpha\sdot\beta v_{t-1}) \\ \theta_t = \theta_{t-1} - \alpha v_t
vt=βvt−1+∇θJ(θt−1−α⋅βvt−1)θt=θt−1−αvt
由上述公式看出,NAG相比Momentum的改进在于对
∇
θ
t
−
1
J
(
θ
)
∇_{\theta_{t-1}} J(\theta)
∇θt−1J(θ)的参数做了修正,计算梯度时预先加入了Momentum计算出的累积动量,使梯度方向更加准确。对上式进一步做变换如下:
v
t
≈
β
v
t
−
1
+
∇
θ
J
(
θ
t
−
1
)
+
β
[
∇
θ
J
(
θ
t
−
1
)
−
∇
θ
J
(
θ
t
−
2
)
]
θ
t
=
θ
t
−
1
−
α
v
t
v_t≈\beta v_{t-1}+∇_{\theta} J(\theta_{t-1})+\beta[∇_{\theta} J(\theta_{t-1})-∇_{\theta} J(\theta_{t-2})] \\ \theta_t = \theta_{t-1} - \alpha v_t
vt≈βvt−1+∇θJ(θt−1)+β[∇θJ(θt−1)−∇θJ(θt−2)]θt=θt−1−αvt
上式( ∇ θ J ( θ t − 1 ) − ∇ θ J ( θ t − 2 ) ) ∇_{\theta} J(\theta_{t-1})-∇_{\theta} J(\theta_{t-2})) ∇θJ(θt−1)−∇θJ(θt−2))计算(i-1)和(i-2)两步的梯度差值,并根据差值进行梯度修正,即二阶指数平滑。具体的解释是,相对于Momentum,NAG评估两步更新之间的梯度变化差异,这个差异相当于对目标函数二阶导数的近似 8 ^8 8。二阶导数能够反映当前梯度的改变势能,当二阶导较大时,证明当前梯度是高阶的“大”(即未来一定时期内会一直较大),因此参数更新量可以适当增加。读者也能够看出,如果将上式 β [ ∇ θ J ( θ t − 1 ) − ∇ θ J ( θ t − 2 ) ] \beta[∇_{\theta} J(\theta_{t-1})-∇_{\theta} J(\theta_{t-2})] β[∇θJ(θt−1)−∇θJ(θt−2)]的部分遮掩,则整个计算变成了接近Momentum的形式,因此可以理解为NAG在Momentum的基础上增加了梯度变化量的有效修正。通俗解释就是:如果梯度处于逐步增加的趋势,则当前参数更新幅度也可以增加;如果梯度改变没有那么明显,则更新幅度需要减小。由此可知NAG相比Momentum更具“前瞻性”,应对梯度改变也更及时。由于上述特点,NAG相比Momentum可以为模型带来更快的收敛速度。至于为什么“梯度预判”约等价于二阶指数平滑,后面会探讨。
接下来,我们从两个角度说明Momentum、NAG的有效性:矢量分析和导数分析。首先是矢量分析,我们分析不同算法所得到的更新方向,我们首先给出SGD迭代的损失下降效果图:
再给出Momentum相比SGD的方向修正说明:
我在第二张图中大致说明了引入动量后的方向修正原理,解释Momentum的更新方向为什么相比SGD更靠近最优值,从而加快模型收敛。然后给出NAG的二阶指数平滑对比Momentum的修正效果:
由图中可以看出,由于梯度计算中融入了动量更新,而动量方向一般都是靠近于最优值的方向,因此相当于把“未来要看到的梯度”提前加入到当前更新中,得到的修正后梯度方向也更靠近于最优值。上图我们也能直观看到,绿色箭头方向相比Momentum中确实更趋向于最优值。
然后我们从导数分析的角度对比SGD、Momentum及NAG,假设某一参数
w
w
w,假设
w
w
w的收敛是凸优化问题,则画出
w
w
w及对应loss函数图,并在图上随机选取一点,标示SGD、Momentum和NAG的梯度。效果如下:
然后说明三种算法所产生的梯度差异究竟在哪,如下图:
根据上图说明如下:
- Momentum计算更新时增加了梯度累积,而由前面凸优化函数图可知,历史梯度比现在梯度要大,因此修正后的参数更新相比SGD更加陡峭;
- 对于NAG,由前文得知它是在Momentum基础上增加了 ( t − 1 ) (t-1) (t−1)步和 ( t − 2 ) (t-2) (t−2)步的梯度差值,而 w w w的凸函数特性使梯度随着步数推移(靠近最优点)逐渐变小,因此 β [ ∇ θ J ( θ t − 1 ) − ∇ θ J ( θ t − 2 ) ] \beta[∇_{\theta} J(\theta_{t-1})-∇_{\theta} J(\theta_{t-2})] β[∇θJ(θt−1)−∇θJ(θt−2)]部分为负值。将负值增加到动量累积中所带来的效果是参数的更新幅度变小了,因而NAG的总体梯度坡度比Momentum变缓了些。另一方面,观察函数图也能得知, x x x点往后接近最优点时参数的更新确实需要放缓,因此证明了NAG的有效性。
因此想必读者也应该理解了,为什么融入预期动量的梯度可以视作二阶指数平滑,因为按凸优化的假设,未来的梯度比现在要小,对应于梯度改变量为负数。因此“动量+未来的梯度”近似于“动量+现在的梯度+最后两步的梯度改变量”;为加深理解,我们再假设 x x x点在更靠近前期的位置,即对应于曲线的更陡峭的点。这里的梯度很大,但梯度变化量小,因此二阶指数平滑时追加的梯度差值小,此时参数可以较快地下降。
总结NAG的优点:
- NAG能够借助二阶指数平滑对梯度进行有效修正,防止更新量太大,最终获得更准确的模型参数;
- NAG尤其对RNN类的网络结构帮助较大。
总结动量类算法的缺点:
- 动量法相比SGD虽加速了模型的收敛,但未能解决一个明显问题,就是不能保证每个参数都收敛到最优点,因为模型训练时不同参数的重要性可能不同、参与更新的频率也可能相差很大,因此动量法无法针对参数调整更新机制,使每一个参数拥有自己的更新状态。最终可能造成某些参数欠收敛的情况。
自适应方法
为什么而来
一个模型在训练时,由于数据的分布差异使得模型的参数经常表现出不同的更新行为。某些参数对应着数据中常见特征的优化,因此训练时更新会更加频繁;而对于不常见的特征,其对应的参数可能更新较少。 最终可能造成下列情况:常见特征的参数会迅速收敛到最优值,而不常见特征的参数得不到充分训练。
因此自适应优化的方法便应运而生,这类方法通常会根据参数参与训练的频率来动态调整学习率,为参与率低的参数适当增加学习率,从而加快收敛到最优值。因此自适应优化方法通常会设置一个参数 w w w的观察量 s ( w , t ) s(w, t) s(w,t),用于表示 w w w参与频率的信息,然后取 η i = η 0 s ( w , t ) + c \eta_i = \frac {\eta_0}{\sqrt{s(w,t)+c}} ηi=s(w,t)+cη0作为 w w w的学习率,其中 c c c为平滑项,防止分母为0.
由式子能够看出, s ( w , t ) s(w, t) s(w,t)与学习率成反比, s ( w , t ) s(w, t) s(w,t)较大时学习率 η i \eta_i ηi较小,表示 w w w的更新较多,当前更新量可以较小些;反正学习率会变大,对应 w w w参与率较低,需要赋予较大的学习率以保持同步更新。
自适学习率应梯度下降—AdaGrad
AdaGrad(Adaptive gradient algorithm)正是自适应学习率的典型代表,也是最早出现的自适应优化算法。AdaGrad对于出现频率较少的特征,对相应参数采用更大的学习率,对于出现频率较多的特征,则其采用较小的学习率。学习率的取值与参数的历史梯度的2-范数(即平方和的开方)。AdaGrad的实现过程如下:
g
t
=
∇
θ
t
−
1
J
(
θ
t
−
1
)
s
t
=
s
t
−
1
+
g
t
2
w
t
=
w
t
−
1
−
η
s
t
+
ϵ
⋅
g
t
g_t = ∇_{\theta_{t-1}} J(\theta_{t-1}) \\ s_t = s_{t-1}+g_t^2\\ w_t = w_{t-1} - \frac {\eta}{\sqrt {s_t + \epsilon}}\sdot g_t
gt=∇θt−1J(θt−1)st=st−1+gt2wt=wt−1−st+ϵη⋅gt
由上述实现不难看出,AdaGrad使用历史梯度的平方和衡量参与率,平方和较大时说明更新频率较大,反之说明频率较小。最后将计算出的 s t s_t st作为分母,并乘上基础学习率 η \eta η以得到当前学习率。其含义是对于梯度累积较小的参数,给予较大的更新量;而对于梯度较大的参数,则减小它的更新幅度。最终训练时参数更新的过程大致为:①前期由于更新较少,参数改变幅度较大;②后期参数变化越来越微弱,直到到达最优点。
优点:
- AdaGrad根据参与率调整学习率,使更新不频繁的参数得到充分学习,对样本稀疏情况下表现较好,也减少了学习率手动调节的繁琐;
- 训练后期学习率将变得很小,有利于准确收敛到最优点,不易造成反复跳跃情况;
- 不容易陷入局部最优值。
缺点:
1.对学习率的控制依旧不够好,训练前期由于梯度较为明显,往往发生学习率极具下降的情况,导致学习率较早就下降到很小的值, 造成收敛慢的问题。
指数加权平均算法—RMSprop
RMSprop(Root Mean Square prop) 的提出正是为解决学习率过早减弱的问题,相比AdaGrad,RMSprop在历史梯度的累加方法上采用指数加权的移动平均,而不是平方和。公式表示如下:
g
t
=
∇
θ
t
−
1
J
(
θ
t
−
1
)
s
t
=
β
s
t
−
1
+
(
1
−
β
)
g
t
2
w
t
=
w
t
−
1
−
η
s
t
+
ϵ
⋅
g
t
g_t = ∇_{\theta_{t-1}} J(\theta_{t-1}) \\ s_t = \beta s_{t-1}+(1-\beta)g_t^2\\ w_t = w_{t-1} - \frac {\eta}{\sqrt {s_t + \epsilon}}\sdot g_t
gt=∇θt−1J(θt−1)st=βst−1+(1−β)gt2wt=wt−1−st+ϵη⋅gt
即累积梯度的更新时为历史梯度和当前梯度都加上系数,以有效放缩,从而防止累积值过大。这操作有些类似于动量的计算,我们先前讲过动量累积时执行一次放缩操作,获得弱化的历史信息并与当前梯度相加,而这里采用放缩是为了弱化
s
t
s_t
st以防止增长过快,使学习率保持一定强度。
优点:
- 有效解决了学习率过早减退问题,加快了模型收敛。
与Momentum组合使用 在实现过程中,RMSprop通常结合Momentum以实现更好效果。例如在PyTorch中RMSprop的执行流程大致如下:
可以看出算法的前4行实现了前面公式的指数加权平均操作,centered决定的是是否“中心化”,如果执行中心化则需要在梯度
v
t
v_t
vt中减去一个一次累积的平方项,获得正则化的梯度,使梯度变化更加稳定;参数
μ
\mu
μ控制是否使用动量方式,动量模式下会对梯度更新量执行动量累积运算,获得平滑的更新量然后更新参数。
AdaDelta
AdaDelta同样借鉴了自适应优化的思想,使用两组累积变量
s
t
s_t
st和
Δ
x
t
\Delta x_t
Δxt,其中
s
t
s_t
st为指数加权平均,作用与RMSprop中类似,而
Δ
x
t
\Delta x_t
Δxt则表示梯度本身变化的累积量,即参数的二阶导数。最终
Δ
x
t
\Delta x_t
Δxt取代
η
\eta
η作为当前学习率,因此理论上AdaDelta无需手动指定学习率。在介绍AdaDelta的算法流程前,定义一个函数RMS,其公式如下:
R
M
S
[
x
]
t
=
E
[
x
2
]
t
+
ϵ
其中
E
[
x
2
]
t
=
ρ
∗
E
[
x
2
]
t
−
1
+
(
1
−
ρ
)
∗
x
2
RMS[x]_t=\sqrt{E[x^2]_t+\epsilon}\\ 其中E[x^2]_t=\rho*E[x^2]_{t-1} + (1-\rho)*x^2
RMS[x]t=E[x2]t+ϵ其中E[x2]t=ρ∗E[x2]t−1+(1−ρ)∗x2
不难看出
E
[
x
2
]
t
E[x^2]_t
E[x2]t的算法和RMSprop的指数加权移动平均类似,上述公式也正是实现了RMSprop中加权累积+根号放缩的过程,作为对学习率的一种权衡。有了上述函数定义,AdaDelta的完整计算过程如下:
E
[
g
2
]
t
=
ρ
∗
E
[
g
2
]
t
−
1
+
(
1
−
ρ
)
∗
g
t
2
R
M
S
[
g
]
t
=
E
[
g
2
]
t
+
ϵ
E
[
Δ
x
2
]
t
−
1
=
ρ
∗
E
[
Δ
x
2
]
t
−
2
+
(
1
−
ρ
)
∗
Δ
x
t
−
2
2
R
M
S
[
Δ
x
]
t
−
1
=
E
[
Δ
x
2
]
t
−
1
+
ϵ
Δ
x
t
=
R
M
S
[
Δ
x
]
t
−
1
R
M
S
[
g
]
t
Δ
θ
=
−
Δ
x
t
∗
g
t
E[g^2]_t=\rho*E[g^2]_{t-1} + (1-\rho)*g_t^2\\ RMS[g]_t=\sqrt{E[g^2]_t+\epsilon}\\ E[\Delta x^2]_{t-1}=\rho*E[\Delta x^2]_{t-2} + (1-\rho)*\Delta x^2_{t-2}\\ RMS[\Delta x]_{t-1}=\sqrt{E[\Delta x^2]_{t-1}+\epsilon}\\ \Delta x_t = \frac {RMS[\Delta x]_{t-1}}{RMS[g]_t}\\ \Delta \theta=-\Delta x_t * g_t
E[g2]t=ρ∗E[g2]t−1+(1−ρ)∗gt2RMS[g]t=E[g2]t+ϵE[Δx2]t−1=ρ∗E[Δx2]t−2+(1−ρ)∗Δxt−22RMS[Δx]t−1=E[Δx2]t−1+ϵΔxt=RMS[g]tRMS[Δx]t−1Δθ=−Δxt∗gt
公式中
E
[
Δ
x
2
]
E[\Delta x^2]
E[Δx2]记录梯度改变量(即参数二阶导数)的加权累积和,经放缩后作为梯度的系数以权衡学习率。
R
M
S
[
Δ
x
]
RMS[\Delta x]
RMS[Δx]根据梯度变化情况对学习率进行调整,公式中它的更新总是比时间步晚1步(即
t
−
1
t-1
t−1),因此它的作用是抵消分母即梯度累积所带来的影响,如梯度突然增加时,
R
M
S
[
Δ
x
]
RMS[\Delta x]
RMS[Δx]起初会使学习率较低,经过几步后梯度的增加反映到了
E
[
Δ
x
2
]
E[\Delta x^2]
E[Δx2]中,学习率也逐渐回升,能够保持一定的收敛速度。在实际中会对
R
M
S
[
g
]
RMS[g]
RMS[g]和
R
M
S
[
Δ
x
]
RMS[\Delta x]
RMS[Δx]进行放缩得到
R
M
S
[
g
]
1
−
ρ
1
t
\frac {RMS[g]}{1-\rho_1^t}
1−ρ1tRMS[g]和
R
M
S
[
Δ
x
]
1
−
ρ
2
t
\frac {RMS[\Delta x]}{1-\rho_2^t}
1−ρ2tRMS[Δx],以防止训练初期取值较小而收敛速度慢。
优点:
- 学习率是根据参数变化调整的,无需特意指定。
注: 自动调整学习率的好处不仅是超参数减少了,节省了调参的麻烦;同时也解决了梯度和参数假设单位的不一致问题(可以理解为单纯使用累积进行放缩,会影响原本的收敛性能,使用 Δ x \Delta x Δx对更新幅度进行调整,可以降低这种影响。
缺点:
- 训练后期,参数可能一直在最优点附近波动,无法收敛。
Adam
Adam(Adaptive Moment Estimation)优化算法是自适应和动量的结合,它同时融合了AdaGrad和RMSprop的思想,也同时具备二者的优点。Adam在二者的基础上,同时使用指数加权移动平均值估计梯度的一阶矩
m
t
m_t
mt和二阶矩
v
t
v_t
vt,分别作为指数衰减均值和历史平方梯度。与RMSprop类似,Adam也对参数进行自适应学习率调整,而更新的梯度来自动量,但相比RMSprop融入了一阶矩,有效改善了训练初期RMSprop的高偏置问题,同时相比后者也多了放缩
v
^
t
←
v
t
/
(
1
−
β
2
t
)
\hat v_t←v_t / (1-\beta_2^t)
v^t←vt/(1−β2t)。Adam参数更新公式如下:
g
t
′
=
η
v
^
t
s
^
t
+
ϵ
g^{'}_t=\frac {\eta \hat v_t}{\sqrt {\hat s_t} + \epsilon}
gt′=s^t+ϵηv^t
原论文里Adam的公式如下:
优点:
- 实现过程简单,计算的高效性;
- 参数的更新不受梯度的伸缩变换影响;
- 很好地实现了步长退火过程(自动调整学习率),受初始学习率的影响小;
- 适用于大规模的数据或大模型场景;
- 适用于梯度稀疏(CV、NLP等任务)或梯度存在很大噪声的问题。
缺点:
- 如果计算时二阶矩爆炸,则很难再次收敛 15 ^{15} 15。
由于Adam应用较为普遍,因此这里增加PyTorch中Adam的实现及接口使用,首先是算法实现伪代码:
看得出来基本与Adam论文中的步骤保持一致,接口形式如下:
下面对主要参数详细介绍:
- params用于传入待更新的模型参数;
- lr代表初始学习率,即算法里的 γ \gamma γ;
- betas需要传入二值列表或元组,第一项代表一阶矩系数 β 1 \beta_1 β1,第二项代表二阶矩系数 β 2 \beta_2 β2;
- eps为分母平滑因子,即公式里的 ϵ \epsilon ϵ;
- weight_decay,即L2正则化的系数;
- amsgrad,来自另一篇工作,解决对非convex目标函数的收敛性;
- maximize,最大化目标函数(使模型欠收敛化)。
Adam变种
AdamW
Loshchilov等人认为在自适应优化算法如Adam下,权重衰减可能无法发挥L2正则化的作用,容易陷入局部最优点。因此提出解耦合权重衰减方法,通过在参数更新中加入L2正则化项使优化器重新获得权重衰减特性,有效提高了Adam的泛化性。参数更新公式如下:
相比Adam增加了对权重的惩罚,因此AdamW可以理解为加了L2正则化的Adam.
PyTorch中AdamW的算法描述如下:
与Adam的实现流程相比,差别在于第6行,Adam中如果weight_decay系数
λ
!
=
0
\lambda!=0
λ!=0,则在梯度中追加权重衰减,但后续还是要参与矩估计;而 AdamW则直接为权重衰减做一次参数更新,后续再进行Adam优化,因此起到了“解耦合”作用,真正发挥了L2正则化。
AMSgrad
上面介绍Adam的torch实现时有提到过,使用历史二阶矩估计的最大值替代当前二阶矩状态更新参数,以解决Adam在某些任务或场景下不能收敛到最优值的问题。修改部分的公式如下:
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
2
v
^
t
m
a
x
=
m
a
x
(
v
^
t
m
a
x
,
v
^
t
)
θ
t
=
θ
t
−
1
−
η
v
^
t
+
ϵ
m
t
v_t= \beta_2v_{t-1}+(1-\beta_2)g_t^2\\ \hat v_t^{max} = max(\hat v_t^{max} , \hat v_t)\\ \theta_{t}=\theta_{t-1}-\frac {\eta}{\sqrt{\hat v_t + \epsilon}}m_t
vt=β2vt−1+(1−β2)gt2v^tmax=max(v^tmax,v^t)θt=θt−1−v^t+ϵηmt
作者实验表明在小数据集上效果较好。
AdaMax
此方案与Adam出自同一篇工作,将二阶矩的L2范式向L- ∞ \infin ∞范式推广(即max),与Adam的差别在学习率分母的计算上,公式如下:
v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 u t = β 2 ∞ v t − 1 + ( 1 − β 2 ∞ ) ∣ g t ∣ ∞ ∞ = m a x ( β 2 ⋅ v t − 1 , ∣ g t ∣ ) θ t = θ t − 1 − η u t m ^ t v_t= \beta_2v_{t-1}+(1-\beta_2)g_t^2\\ u_t = \sqrt [\infin]{\beta_2^\infin v_{t-1}+(1-\beta_2^\infin)|g_t|^\infin}\\ =max(\beta_2\sdot v_{t-1}, |g_t|)\\ \theta_t = \theta_{t-1}-\frac {\eta}{u_t}\hat m_t vt=β2vt−1+(1−β2)gt2ut=∞β2∞vt−1+(1−β2∞)∣gt∣∞=max(β2⋅vt−1,∣gt∣)θt=θt−1−utηm^t
最终使用 u t u_t ut作为步长的分母,实质上也是由二阶动量向P阶动量的推广。实验表明在流式数据(语音)任务上表现较好。
Nadam
既然Adam是动量与RMSprop的结合,那很自然地想到NAG可以作为替代动量的更好方案,因此就有了NAG与RMSprop结合的Nadam算法。首先给出Adam的一阶矩和参数更新公式:
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
m
^
t
=
m
t
1
−
β
1
t
θ
t
+
1
=
θ
t
−
η
v
^
t
+
ϵ
m
^
t
m_t = \beta_1m_{t-1}+(1-\beta_1)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
mt=β1mt−1+(1−β1)gtm^t=1−β1tmtθt+1=θt−v^t+ϵηm^t
将第三行参数更新部分根据一阶矩计算展开,得到如下:
θ
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}(\frac {\beta_1m_{t-1}}{1-\beta_1^t}+\frac {(1-\beta_1)g_t}{1-\beta_1^t})
θt+1=θt−v^t+ϵη(1−β1tβ1mt−1+1−β1t(1−β1)gt)
进一步替换式中
m
t
−
1
1
−
β
1
t
\frac {m_{t-1}}{1-\beta_1^t}
1−β1tmt−1为
m
^
t
−
1
\hat m_{t-1}
m^t−1,得到如下:
θ
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}(\beta_1\hat m_{t-1}+\frac {(1-\beta_1)g_t}{1-\beta_1^t})
θt+1=θt−v^t+ϵη(β1m^t−1+1−β1t(1−β1)gt)
对于Nesterov算法,将未来步的梯度应用于当前更新策略中,因此上式的
m
^
t
−
1
\hat m_{t-1}
m^t−1即过去动量的偏差修正被替换为当前步的偏差修正,以获得一定预期应变性。形式如下:
θ
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}(\beta_1\hat m_t+\frac {(1-\beta_1)g_t}{1-\beta_1^t})
θt+1=θt−v^t+ϵη(β1m^t+1−β1t(1−β1)gt)
Radam
Adam训练时学习率方差较大,容易陷入局部最优解的问题,因此提出Radam(Rectified Adam)
18
^{18}
18,使训练初期保持较小的学习率,起到warm-up作用。首先指出不使用warm-up时训练初期会带来很多的错误决策,容易陷入局部最优点,造成收敛缓慢,而尝试了warm-up后能够减轻高方差。因此设计整流器(rectifier),允许前期使用自适应动量以缓慢收敛,后期直接使用一阶矩更新。算法如下:
第2行定义移动平均值(SMA)的最大长度,第8行计算当前SMA长度,随后根据长度决定计算方法。按算法中描述,如果长度大于4,则更新参数时加入二阶矩修正和方差整流项;否则使用非自适应一阶矩更新。gi
RAdam根据训练时期动态选择自适应或非自适应学习率,为Adam提供了动态warmup能力,且这种warm-up相比传统学习率scheduler的warm-up要好。实验表明Radam具有更快的收敛速率,且对初始学习率的鲁棒性更强。
Yogi
解决了Adam在凸优化问题下二阶矩爆炸时的历史动量遗忘问题,并重写了
s
t
s_t
st的计算方法,首先对Adam的二阶矩公式变换如下:
s
t
=
s
t
−
1
+
(
1
−
β
2
)
(
g
t
2
−
s
t
−
1
)
s_t = s_{t-1}+(1-\beta_2)(g_t^2-s_{t-1})
st=st−1+(1−β2)(gt2−st−1)
上述公式等价于原始二阶矩计算,读者可自行验证。然后论文将上述计算改进如下:
s
t
=
s
t
−
1
+
(
1
−
β
2
)
g
t
2
⊙
s
g
n
(
g
t
2
−
s
t
−
1
)
s_t = s_{t-1}+(1-\beta_2)g_t^2 \odot sgn(g_t^2-s_{t-1})
st=st−1+(1−β2)gt2⊙sgn(gt2−st−1)
其中sgn为符号函数,上述公式实质是对当前二阶矩小于历史累积时的特殊处理,使更新不再受偏差影响。Yogi的提出也是为了更好地控制学习率。
SparseAdam
一种专门用于稀疏张量的Adam优化算法,执行过程中只计算包含梯度的神经元,并更新对应的参数。
其它经典工作
Rprop
在批量训练过程中,参数的梯度随着数据的不同而存在符号差异,因而造成全局学习率不足以处理这些情况。故提出基于梯度符号的步长调整策略,Rprop中的R即resilient(弹性),解释为根据历史两次梯度的变化弹性调整当前学习率。Rprop算法如下:
算法判断了当前和上一步的梯度符号是否异同,如果相同,则学习率
η
\eta
η为上一步学习率与
η
+
\eta_+
η+(加速因子)的乘积,起到增大当前学习率的作用;如果符号不同,则
η
\eta
η为上一步学习率与
η
−
\eta_-
η−(减速因子)的乘积,意为减小学习率;等于零则学习率保持上一步不变。为防止学习率变得过大/过小,设置上下限
Γ
m
a
x
\Gamma_{max}
Γmax和
Γ
m
i
n
\Gamma_{min}
Γmin,如果学习率超出界限即停止。
优点:
- 确保了权重更新幅度更加贴合当前梯度状态,如果符号大于0,则说明多个batch的数据支持当前参数往同一个方向改变,因此可以适当增加学习率以加快收敛;如果符号小于0,说明多个batch下的数据在当前参数的更新方向上出现歧义,则需要适当减缓更新速度。
缺点:
- 在大规模数据且使用mini-batch的场景下效果会变差,因为不考虑数据分布而仅仅按照符号特性改变学习率,会给参数带来偏差。
BFGS
BFGS在牛顿法的基础上融合了SGD和梯度下降的思想,是针对目标函数非凸情况下的优化算法,相比SGD等具有更快的迭代速度。注意这里的牛顿法和前面的NAG不是一个概念,牛顿法旨在求解 f ( x ) = 0 f(x)=0 f(x)=0的根 x x x,步骤如下:
- 随机产生点 x 0 x_0 x0;
- 按下列方式迭代: x k = x k − 1 − f ( x k − 1 ) f ′ ( x k − 1 ) x_k = x_{k-1}-\frac {f(x_{k-1})}{f'({x_{k-1}})} xk=xk−1−f′(xk−1)f(xk−1);
- 结束条件:如果某一次迭代后的 x k x_k xk同前一次 x k − 1 x_{k-1} xk−1相差在某个阈值内,则结束迭代,将 x k x_k xk作为 f ( x ) = 0 f(x)=0 f(x)=0的根。
在梯度下降中需要求解的是
f
′
(
x
)
=
0
f'(x)=0
f′(x)=0的根,因此迭代公式变为:
x
k
=
x
k
−
1
−
f
′
(
x
k
−
1
)
f
′
′
(
x
k
−
1
)
x_k = x_{k-1}-\frac {f'(x_{k-1})}{f''({x_{k-1}})}
xk=xk−1−f′′(xk−1)f′(xk−1)
推导一下计算过程,首先对导函数
f
′
(
x
)
f'(x)
f′(x)做二阶泰勒展开如下:
f
′
(
x
)
=
f
′
(
x
k
)
+
(
x
−
x
k
)
f
′
′
(
x
−
x
k
)
+
o
(
f
′
′
(
x
−
x
k
)
)
f'(x)=f'(x_k)+(x-x_k)f''(x-x_k)+o(f''(x-x_k))
f′(x)=f′(xk)+(x−xk)f′′(x−xk)+o(f′′(x−xk))
直接忽略高阶无穷小,变为等号关系:
f
′
(
x
)
=
f
′
(
x
k
)
+
(
x
−
x
k
)
f
′
′
(
x
−
x
k
)
f'(x)=f'(x_k)+(x-x_k)f''(x-x_k)
f′(x)=f′(xk)+(x−xk)f′′(x−xk)
求解目标是
f
′
(
x
)
=
0
f'(x)=0
f′(x)=0,即上述
f
′
(
x
k
)
+
(
x
−
x
k
)
f
′
′
(
x
−
x
k
)
=
0
f'(x_k)+(x-x_k)f''(x-x_k)=0
f′(xk)+(x−xk)f′′(x−xk)=0. 由于
f
′
(
x
k
)
=
0
f'(x_k)=0
f′(xk)=0,因此公式变换如下:
首先等号两边同乘倒数
f
′
′
−
1
(
x
−
x
k
)
f''^{-1}(x-x_k)
f′′−1(x−xk),得到:
f
′
′
−
1
(
x
−
x
k
)
f
′
(
x
)
=
x
−
x
k
f''^{-1}(x-x_k)f'(x)=x-x_k
f′′−1(x−xk)f′(x)=x−xk
再进行变换得到:
x
k
=
x
−
f
′
′
−
1
(
x
−
x
k
)
f
′
(
x
)
x_k=x-f''^{-1}(x-x_k)f'(x)
xk=x−f′′−1(x−xk)f′(x)
使用Hessian矩阵表示二阶导数,同时改为递进关系,公式变为:
x
k
+
1
=
x
k
−
H
k
−
1
⋅
g
k
x_{k+1} = x_{k}-H_{k}^{-1}\sdot g_k
xk+1=xk−Hk−1⋅gk
这里需要求解Hessian逆矩阵
H
k
−
1
H_{k}^{-1}
Hk−1,直接计算较为困难,因此通过迭代不断逼近其表示:
D
K
+
1
=
(
I
−
s
k
y
k
T
y
k
T
s
k
)
D
k
(
I
−
y
k
s
k
T
y
k
T
s
k
)
+
s
k
s
k
T
y
k
T
s
k
D_{K+1}=(I-\frac {s_ky_k^T}{y_k^Ts_k})D_k(I-\frac {y_ks_k^T}{y_k^Ts_k})+\frac {s_ks_k^T}{y_k^Ts_k}
DK+1=(I−ykTskskykT)Dk(I−ykTskykskT)+ykTskskskT
其中
s
k
=
x
k
+
1
−
x
k
s_k=x_{k+1}-x_k
sk=xk+1−xk,
y
k
=
g
k
+
1
−
g
k
y_k=g_{k+1}-g_k
yk=gk+1−gk,定义
D
0
=
I
D_0=I
D0=I(单位矩阵)。
以上即BFGS算法,用于近似Hessian逆矩阵
H
k
−
1
H_k^{-1}
Hk−1.
L-BFGS
BFGS计算近似逆矩阵时要保存上一步的 D k D_k Dk,会带来很大的内存开销。因此提出只存储 s s s和 y y y的中间结果,每次都从 I I I开始重新计算。如参数量为10000,使用BFGS计算 D 10 D_{10} D10,如果缓存 D k D_k Dk则需要 1 ∗ 1 0 8 1*10^8 1∗108单位的存储空间;而缓存 ( s 0 , s 1 , . . . , s 9 ) (s_0, s_1, ... , s_9) (s0,s1,...,s9)和 ( y 0 , y 1 , . . . , y 9 ) (y_0, y_1, ... , y_9) (y0,y1,...,y9),则仅需要 2 ∗ 10 ∗ 10000 = 200000 2 * 10 * 10000=200000 2∗10∗10000=200000单位存储。
而对于迭代轮数较大的情况,例如上述迭代到500+步时,同样会造成内存耗费。此时可以丢弃前面若干项,保留最近n项结果,此即L-BGFS实现。假设是当数据增多时,采集到的 s s s和 y y y样本足以反映基本函数形态,能够获得较精确的 H k − 1 H_k^{-1} Hk−1 (比如你在直角坐标系上随机选一个区间,如[0, 0.1],想象一下区间内有很多x点及对应的导数坡度,你也可以根据这些大致描绘出这个函数是什么形状)。
近期成果
分布式方案
背景
随着深度学习硬件的发展,以及训练数据的增长,分布式训练开始变得越来越普遍,由此带来了更大的训练批量,使用传统的优化器会变得非常不稳定,容易陷入局部最优点。因此出现了很多优化器的改进工作。
层级自适应
首先引入“层级自适应”的概念,提出的主要背景是更新时梯度和参数的模给参数调整带来的影响,普遍认为当梯度的模较大时,参数更新会缺乏稳定性。因此出现了使用参数和梯度的模控制学习率的方法,这类方法一般对更新量系数做如下修改:
θ
t
=
θ
t
−
1
−
γ
∣
∣
θ
t
∣
∣
2
∣
∣
h
t
∣
∣
2
h
t
\theta_t = \theta_{t-1} - \gamma \frac {||\theta_t||_2}{||h_t||_2} h_t
θt=θt−1−γ∣∣ht∣∣2∣∣θt∣∣2ht
步长计算中多出了 ∣ ∣ θ t ∣ ∣ 2 ∣ ∣ h t ∣ ∣ 2 \frac {||\theta_t||_2}{||h_t||_2} ∣∣ht∣∣2∣∣θt∣∣2,即参数的模与梯度的模之比。这个比率也叫“信任比率”,它定义为每个网络层的权值范数与梯度范数的比值,并且认为比例较大时会使训练不稳定,而比例较小会导致收敛过慢,因而需要针对具体网络层调整学习率。
逐层学习率策略可以解释为:当比率较小时,学习率可以适当降低,类似于训练初期的warm-up;而比率较大时,学习率适当提升,可以避免陷入局部最优点。
LARS
有研究者认为模型参数的不稳定收敛是因为参数本身和对应梯度的欠关联考虑,对此提出了融入信任比率的LARS(分层自适应速率调整,Layer-wise adaptive rate scaling)优化方法。搭配LARS的SGD算法如下:
算法的公式
∣
∣
w
t
l
∣
∣
∣
∣
g
t
l
∣
∣
+
β
∣
∣
w
t
l
∣
∣
\frac {||w_t^l||}{||g_t^l||+\beta ||w_t^l||}
∣∣gtl∣∣+β∣∣wtl∣∣∣∣wtl∣∣即层级权重范数与梯度范数之比,它起计算逐层学习率
λ
\lambda
λ的作用。
优点:
- 改善了较大batcn和学习率下的训练不稳定、模型不收敛问题。
LAMB
谷歌于2019年提出LAMB(Layer-wise Adaptive Moments optimizer for Batch training)优化算法,用于较大batch的训练任务,适合分布式训练的单次更新大量样本的场景。LAMB结合了Adam和LARS中的方法,根据权重和梯度的变化动态调整学习率,算法如下:
能够明显看出参数更新时乘上的
ϕ
(
∣
∣
x
t
(
i
)
∣
∣
∣
∣
r
t
(
i
)
+
λ
x
t
i
∣
∣
)
\phi(\frac {||x_t^{(i)}||}{||r_t^{(i)}+\lambda x_t^{i}||})
ϕ(∣∣rt(i)+λxti∣∣∣∣xt(i)∣∣)即等同于LARS中的norm系数,只是分母的计算略有不同,LARS计算梯度与权值的范数和,而LAMB计算和的范数;同时也是利用了Adam的更新规则。LAMB与LARS在SQuAD上的效果对比如下:
使用ResNet-50在ImageNet上实验,与其它主流优化器的效果对比如下:
AdaFactor
Adam需要同时缓存一、二阶矩,对显存的占用也比较大,因此提出AdaFactor,它具备自适应学习率的特性,但较传统优化器更节省显存。AdaFactor放弃了使用动量,从而减少了
m
m
m缓存;为进一步降低变量占用,对二阶矩
v
v
v也采用低秩分解,使用非负矩阵分解技术将大的参数矩阵拆分成低阶矩阵相乘,得到分解后的滑动平均值
v
t
(
r
)
v_t^{(r)}
vt(r)、
v
t
(
c
)
v_t^{(c)}
vt(c),并调整学习率;AdaFactor还参考了LAMB,根据权值和初始学习率调整更新步长。整体计算如下:
公式第5行计算矩阵的按行指数平均,获得列向量 R t R_t Rt(因为按行平均后列维度变为1),其中 1 m {1_m} 1m为全1向量,用于对指定行求和;类似地第6行计算矩阵的按列指数平均得到行向量 C t C_t Ct. 第7行 R t C t R_tC_t RtCt计算得到低秩的梯度平方矩阵,并除以 1 n T R t 1_n^T R_t 1nTRt完成放缩;最后将 V ^ t \sqrt {\hat V_t} V^t加入参数更新中实现自适应学习率。说明一下第3行和第9行,其中 R M S ( x ) = ∑ i = 1 n x i 2 n RMS(x) = \sqrt {\frac {\sum_{i=1}^n{x_i^2}}{n}} RMS(x)=n∑i=1nxi2,含义为放缩了 n \sqrt n n的x模长。第3行的 m a x max max表示如果RMS模长小于 ϵ 2 \epsilon_2 ϵ2,则取值为 ϵ 2 \epsilon_2 ϵ2,否则为RMS结果,其含义也类似于层级自适应方案,参数范数较大时会鼓励步长的增加;第9行的 m a x max max表示如果RMS模长小于d,则取值为1,否则为RMS结果,实质上也类似根据梯度范数调整步长,梯度较大时RMS也较大,学习率也会变小。
Lion
首先不得不提及的是符号类更新,这类方法通常只取梯度变化的绝对方向,即正向或负向,与梯度值无关。一个典型的代表就是SIGNUM,它在Momentum的基础上修改参数更新为纯符号计算,过程如下:
m
t
=
β
m
t
−
1
+
(
1
−
β
)
g
t
u
t
=
s
i
g
n
(
m
t
)
θ
t
=
θ
t
−
1
−
η
t
u
t
m_t = \beta m_{t-1}+(1-\beta)g_t \\ u_t=sign(m_t)\\ \theta_t = \theta_{t-1}-\eta_tu_t
mt=βmt−1+(1−β)gtut=sign(mt)θt=θt−1−ηtut
其中
s
i
g
n
sign
sign为符号函数,含义是用符号替代动量更新,即更新时只与移动平均值的正负有关,与大小无关。符号优化的目的是减少分布式训练时优化器参数的通信量,由原来的浮点传输变为符号传输,从而加快了训练速度。归并时按投票原则取得票较多的符号作为梯度方向,方法如下:
而Lion是谷歌在2023年的一项新成果,同样融入了符号计算代替梯度,不仅减少了变量缓存,使迭代速度更快,而且效果上也比Adam等方法更好。Lion的计算过程如下:
Lion每次更新时同样只与移动平均值的正负有关,与大小无关。对比公式能够看出,相比SIGNUM,Lion计算动量和符号时使用了不同的
β
\beta
β超参,且增加了Weight decay. Lion在多项NLG和NLU任务上效果优于AdamW和AdaFactor.
符号更新为什么有效 Lion相比SGD将梯度更新量简化为符号更新,不仅训练上提高了分布式通信效率,同时效果也优于基于梯度的系列算法。文中认为符号量相比确切的梯度包含了更多噪声,能够有效训练模型的抗干扰能力,因此模型鲁棒性更强;还有一点是由于模型参数的初始化一般都是按某种分布(正态等)随机的,因此梯度大小也与参数的取值有关,符号代替梯度从某种意义上使所有参数平权,更新不会受对应梯度影响,有力地挖掘了潜在能力,从而更有可能收敛到最优解。
思考 随者本文介绍的优化器技术的演进,可能读者也发现了一个趋势—参数的更新逐渐由狭义梯度变为广义梯度。起初的Adam系列,虽然融合了二阶矩和动量,但都是聚焦于当前参数的梯度变化;到了LARS系列,出现了分层自适应学习率技术,参数的更新开始受同层其它参数的影响;而更晚出现的Lion则是直接抛弃了梯度范式,将参数的优化转向更一般的方向特征(符号量),学习率与梯度无关。广义的更新相比具体到参数本身的更新更能切入到模型的一般性,为模型的更优收敛提供了可能。
参考链接
- https://zhuanlan.zhihu.com/p/350043290
- https://sherlock.blog.csdn.net/article/details/80071967(不同优化器的动态可视化对比)
- https://blog.csdn.net/weixin_40170902/article/details/80092628
- https://blog.csdn.net/google19890102/article/details/69942970
- https://blog.csdn.net/tcn760/article/details/123965374
- https://zh.d2l.ai/chapter_optimization/index.html (Dive Into Deep Learning中的优化器介绍)
- https://arxiv.org/pdf/1609.04747.pdf (优化器综述)
- Ruder S. An overview of gradient descent optimization algorithms[J]. arXiv preprint arXiv:1609.04747, 2016. (优化器算法总结)
- Qian N. On the momentum term in gradient descent learning algorithms[J]. Neural networks, 1999, 12(1): 145-151. (Momentum的物理含义及算法)
- Nesterov Y. A method for unconstrained convex minimization problem with the rate of convergence O (1/k^ 2)[C]//Doklady an ussr. 1983, 269: 543-547. (Nesterov论文)
- https://zhuanlan.zhihu.com/p/22810533/ (Nesterov有效性证明)
- Duchi J, Hazan E, Singer Y. Adaptive subgradient methods for online learning and stochastic optimization[J]. Journal of machine learning research, 2011, 12(7). (AdaGrad论文)
- Zeiler M D. Adadelta: an adaptive learning rate method[J]. arXiv preprint arXiv:1212.5701, 2012. (AdaDelta论文)
- Kingma D P, Ba J. Adam: A method for stochastic optimization[J]. arXiv preprint arXiv:1412.6980, 2014. (Adam论文)
- S. J. Reddi, S. Kale, and S. Kumar, “On the convergence of adam and beyond,” arXiv preprint arXiv:1904.09237, 2019. (AMSGrad论文)
- Reddi, S. J., Kale, S., & Kumar, S. (2019). On the convergence of adam and beyond. arXiv preprint arXiv:1904.09237. (指出Adam的二阶矩发散问题)
- https://www.ruder.io/deep-learning-optimization-2017/ (Adam改进研究总结2017年)
- https://arxiv.org/pdf/1908.03265v1.pdf (Radam)
- https://arxiv.org/pdf/1708.03888.pdf (LARS)
- https://arxiv.org/pdf/1904.00962v3.pdf (LAMB)
- https://arxiv.org/pdf/1804.04235.pdf (AdaFactor)
- https://kexue.fm/archives/7094
- https://arxiv.org/abs/1802.04434 (SIGNUM)
- https://arxiv.org/pdf/2302.06675.pdf (Lion)