文章目录
1.介绍
在机器学习模型训练时,模型优化算法是必不可少的,例如常见的梯度下降优化算法SGD,这也是大多数机器学习’炼丹师‘第一次接触机器学习时使用的优化算法,也是最容易理解的,但是机器学习任务中模型千变万化,很难做到一种优化算法“通吃”所有模型。因此对于不同的模型,需要对原始的梯度下降优化算法不断的改进优化。下面就对梯度下降优化等常见的优化算法及其改进算法做一一介绍。
2.常见优化算法
2.1 梯度下降法及其变种
2.1.1 批梯度下降法
批梯度下降法(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
注意:
- 对于损失函数为凸函数的情况,批梯度下降法能够收敛到全局最小值;
- 对于损失函数为非凸函数的情况,批梯度下降法则能够收敛到局部最小值。
2.1.2 随机梯度下降法
批梯度下降法(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
2.1.3 小批量梯度下降法
小批量梯度下降法(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很难从这些鞍点中逃开。
2.2 梯度下降法的优化算法
在正式学习各种SGD的改进的优化算法之前,可以先通过这中动图感受下各个优化算法收敛速度和收敛效果。


2.2.1 Momentum-动量法
SGD很难通过陡谷,即在一个维度的表面弯曲程度远大于其他维度的区域,这种情况通常出现在局部最优点附近,这种情况下,SGD在不断波动下通过陡谷的斜坡,在沿着谷底到局部最优点的路径上缓慢前进,过程如下图(a)所示:

如上图(b)所示,动量法是一种帮助SGD在相关方向上加速并抑制摇摆的方法,利于处理非平稳梯度,动量法是将上一次更新量的一个分量γ增加到当前的更新量中,公式如下:
ν
t
=
γ
ν
t
−
1
+
η
▽
θ
J
(
θ
)
(
1
)
\nu_{t} = \gamma\nu_{t-1} + \eta\bigtriangledown_{\theta}J(\theta) \qquad (1)
νt=γνt−1+η▽θJ(θ)(1)
θ
=
θ
−
ν
t
(
2
)
\theta = \theta - \nu_t \qquad (2)
θ=θ−νt(2)
- 上面公式(1)等号后面,γ表示使用上次更新量的权重,决定了动量的大小,η部分跟前面SGD参数更新量完全相同;
- 公式(2)中,不再像前面SGD公式中直接将学习率大小体现出来了,而是整个的包含在νt中了。在后面的其他改进SGD的优化算法中也是类似的做法。
动量项γ通常可以设置成0.9。
可以这样来理解动量。参考文献[1]中这样的比喻很好:从山坡上往下推一个球,在往下滚动的过程中累积动量,速度越来越快,如果有空气阻力,则γ<1。对于参数更新也是如此,对于在当前梯度点处有相同方向的维度,动量项增加,对于在梯度点处改变方向的维度,其动量项减小,因此我们可以获得更快的收敛速度,同时可以减小频繁的波动。
2.2.2 Nesterov-加速梯度下降法
接着上面举的例子,如果球盲目的沿着斜率方向向下滚动,结果也不一定总是令人满意,我们希望有一个智能的球,能够知道它将要去哪,如果遇到斜率将要上升时,能够知道减速。
Nesterov加速梯度下降法(Nesterov accelerated gradient,NAG)是一种能够给动量项γνt−1
一种预知能力的方法。我们使用动量项更新参数,通过计算θ - γνt−1
能够告诉我们参数未来位置的一个近似值,也就是告诉我们参数将大致变为多少。通过计算参数未来的近似位置的梯度,即使用θ - γνt−1
计算梯度,而不是使用θ
来计算梯度,我们可以更加高效的求解(我自己理解为:这里的一次参数更新近似于动量法的两次更新,所以是加速了):
ν
t
=
γ
ν
t
−
1
+
η
▽
θ
J
(
θ
−
γ
ν
t
−
1
)
(
3
)
\nu_{t} = \gamma\nu_{t-1} + \eta\bigtriangledown_{\theta}J(\theta - \gamma\nu_{t-1}) \qquad (3)
νt=γνt−1+η▽θJ(θ−γνt−1)(3)
θ
=
θ
−
ν
t
(
4
)
\theta = \theta - \nu_{t} \qquad (4)
θ=θ−νt(4)
上面公式(3)中,η部分,表示假设更新量为上次梯度上的动量大小,这是个近似更新量,然后再基于这个更新后的损失函数对于参数θ的一阶导数作为当前新的梯度,即公式(3)中η后面的部分。到这里就可以直接套用动量优化算法中公式(1)了,因此上面我理解为这种方式的一次参数更新的效果近似于动量法的两次参数更新的效果,所以理论上是加速了。
因为NAG-加速梯度下降法跟Momentum-动量法相似之处比较多,所以可以通过下面的一幅图对比两者的关系:
一般设置动量项γ的大小为0.9左右!
- 动量法:首先计算当前的梯度值(箭头线1),然后在更新的累积梯度上前进一大步(箭头线2);
- 加速梯度下降法:首先作一个预见性的更新,即在先前累积梯度方向上前进一大步(箭头线3),并计算出梯度作为一个修正(箭头线4),修正后为箭头线5。这里的预见性更新增强了算法的响应能力(即加速),同时通过修正防止了前进地太快。这一点对于很多RNN的任务的性能提升有着重要的意义。
对于上面的动量法和NAG法,是通过使参数更新适应损失函数的斜率以加速SGD;那么为了进一步优化,考虑使得参数的更新适应每一个单独参数,以根据每一个参数来决定是大的更新还是小的更新。这也是后面的优化算法设计的初衷。
2.2.3 Adagrad-自适应梯度
Adagrad是一种适应参数的梯度下降优化算法,其自适应性可以个性化到特征级别,出现次数较少的特征的,会使用更大的学习率,出现次数较多的特征,会使用较小的学习率,因此Adagrad适合于稀疏数据的深度神经网络模型。
- Dean等人[4]发现Adagrad能够极大提高了SGD的鲁棒性并将其应用于Google的大规模神经网络的训练,其中包含了YouTube视频中的猫的识别;
- Pennington等人[15]利用Adagrad训练Glove词向量,因为低频词比高频词需要更大的步长。
Agagrad在每次更新所有的参数θ
时,对于每个参数使用不同的学习率,我们先看下如何对不同的参数进行更新的。下面公式(5)表示在t时刻损失函数关于参数θi
的梯度:
g
t
,
i
=
▽
θ
J
(
θ
i
)
(
5
)
g_{t,i} = \bigtriangledown_{\theta}J(\theta_{i}) \qquad (5)
gt,i=▽θJ(θi)(5)
如果受用固定步长的学习率,则参数更新公式为:
θ
t
+
1
,
i
=
θ
t
,
i
−
η
∗
g
t
,
i
(
6
)
\theta_{t+1, i} = \theta_{t, i} - \eta*g_{t, i} \qquad (6)
θt+1,i=θt,i−η∗gt,i(6)
现在加入对不同参数个性化的步长因子,即在t时刻,基于对不同参数计算过的历史梯度,Adagrad修正了每一个参数的学习率:
θ
t
+
1
,
i
=
θ
t
,
i
−
η
G
t
,
i
i
+
ϵ
∗
g
t
,
i
,
G
t
∈
R
d
×
d
(
7
)
\theta_{t+1, i} = \theta_{t, i} - \frac{\eta}{\sqrt{G_{t, ii} + \epsilon}}*g_{t, i},\quad G_{t} \in R^{d\times d} \qquad (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
)
G_{t, ii} = \sum_{k = 1}^{t}g_{k, i}^2 \qquad (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_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{G_{t} + \epsilon}}\odot g_{t} \qquad (9)
θt+1=θt−Gt+ϵη⊙gt(9)
Adagrad算法的优缺点如下:
- 优点:主要优点就是无需手动调整学习率,基本上采用 0.01 即可。
- 缺点:由于其在分母中累加梯度的平方,每次增加一个正项,随着训练过程积累,会导致学习率越来越小,当学习率变得无限小时Adagrad算法将无法获得额外的信息更新。
下面将要介绍算法也是针对Adagrad的缺点进行改进的。
2.2.4 Adadelta
Adadelta算法完全移除了学习率,不再需要人工设置学习率参数。
Adadelta算法是Adagrad的一种扩展,以解决Adagrad学习速率单调递减的缺点。Adadelta算法无需存储历史梯度的平方和,而是将梯度的平方递归地表示成所有历史梯度的均值,因此在t
时刻的均值只取决于先前的均值和当前的梯度:
E
[
g
2
]
t
=
γ
E
[
g
2
]
t
−
1
+
(
1
−
γ
)
g
t
2
(
10
)
E[g^2]_{t} = \gamma E[g^2]_{t-1} + (1 - \gamma)g_{t}^2 \qquad (10)
E[g2]t=γE[g2]t−1+(1−γ)gt2(10)
其中γ与动量项相似,可以设置成0.9。
对于参数更新向量我们可以表示成:
△
θ
t
=
−
η
⋅
g
t
,
i
(
S
G
D
)
(
11
)
\triangle\theta_{t} = -\eta \cdot g_{t, i} \qquad\qquad (SGD) \qquad (11)
△θt=−η⋅gt,i(SGD)(11)
△
θ
t
=
−
η
G
t
+
ϵ
⋅
g
t
(
A
d
a
g
r
a
d
)
(
12
)
\triangle\theta_{t} = -\frac{\eta}{\sqrt{G_{t} + \epsilon}} \cdot g_{t} \qquad\qquad (Adagrad) \qquad (12)
△θt=−Gt+ϵη⋅gt(Adagrad)(12)
那么,我们直接将Gt
替换成历史梯度均值则为:
△
θ
t
=
−
η
E
[
g
2
]
t
+
ϵ
⋅
g
t
(
13
)
\triangle\theta_{t} = -\frac{\eta}{\sqrt{E[g^2]_{t} + \epsilon}} \cdot g_{t} \qquad (13)
△θt=−E[g2]t+ϵη⋅gt(13)
上述公式中由于分母就是均方根,所以可以直接简写为:
△
θ
t
=
−
η
R
M
S
E
[
g
]
t
⋅
g
t
(
14
)
\triangle\theta_{t} = -\frac{\eta}{RMSE[g]_{t}} \cdot g_{t} \qquad (14)
△θt=−RMSE[g]tη⋅gt(14)
Adadelta[7]直接指出了上述几种优化算法中更新规则与参数的单位不一致的问题,为此Adadelta实现了这个要求,类似于梯度的动量形式的均值,作者首次提出了参数的动量形式的均值,如下公式所示:
E
[
△
θ
2
]
t
=
γ
E
[
△
θ
2
]
t
−
1
+
(
1
−
γ
)
△
θ
2
(
15
)
E[\triangle \theta^2]_{t} = \gamma E[\triangle \theta^2]_{t-1} + (1 - \gamma)\triangle \theta^2 \qquad (15)
E[△θ2]t=γE[△θ2]t−1+(1−γ)△θ2(15)
那么参数更新的均方根为:
R
M
S
[
△
θ
]
t
=
E
[
△
θ
2
]
t
+
ϵ
(
16
)
RMS[\triangle\theta]_{t} = \sqrt{E[\triangle \theta^2]_{t} + \epsilon} \qquad (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
)
\triangle\theta_{t} = -\frac{RMS[\triangle\theta]_{t-1}}{RMSE[g]_{t}} \cdot g_{t} \qquad (17)
△θt=−RMSE[g]tRMS[△θ]t−1⋅gt(17)
θ
t
=
θ
t
+
△
θ
t
(
18
)
\theta_{t} = \theta_{t} + \triangle\theta_{t} \qquad (18)
θt=θt+△θt(18)
使用Adadelta优化算法,我们无需设置学习率,因为公式中已经移除了学习率的超参数。
2.2.5 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
)
E[g^2]_{t} = 0.9E[g^2]_{t-1} + 0.1g_{t}^2 \qquad (19)
E[g2]t=0.9E[g2]t−1+0.1gt2(19)
θ
t
+
1
=
θ
t
−
η
E
[
g
2
]
t
+
ϵ
g
t
(
20
)
\theta_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{E[g^2]_{t} + \epsilon}}g_{t} \qquad (20)
θt+1=θt−E[g2]t+ϵηgt(20)
因此,RMSprop也是将学习率分解成平方梯度的指数衰减的平均,对于学习率η,建议选择 0.001。
2.2.6 Adam-自适应矩估计
自适应矩估计(Adaptive Moment Estimation, Adam)也是一种会对每一个参数会计算出自适应学习率的算法。它一个动量算法和RMSprop算法的结合体,既考虑到了利用动量项来加速训练过程,又考虑到对于学习率的约束。Adam也会计算出来一个指数衰减的历史平方梯度的平均vt ,Adam同时还计算一个指数衰减的历史梯度的平均mt,类似于动量:
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
(
21
)
m_{t} = \beta_1m_{t-1} + (1 - \beta_1)g_{t} \qquad (21)
mt=β1mt−1+(1−β1)gt(21)
ν
t
=
β
2
ν
t
−
1
+
(
1
−
β
2
)
g
t
2
(
22
)
\nu_{t} = \beta_2\nu_{t-1} + (1 - \beta_2)g_{t}^2 \qquad (22)
νt=β2νt−1+(1−β2)gt2(22)
因此,mt
是对梯度的一阶矩的估计,νt
是对梯度的二阶矩(非确定性误差)的估计。
但是当mt
和νt
都初始化为0时,特别是在初始化的步骤和衰减率都很小时(β1
和β2接近于1
),Adam比较接近于0,这对于参数更新并不友好(更新太慢),Adam中是通过计算偏差矫正的一阶矩估计和二阶矩估计来抵消偏差的,公式如下:
m
^
t
=
m
t
1
−
β
1
t
(
23
)
\hat m_{t} = \frac{m_{t}}{1 - \beta_1^t} \qquad (23)
m^t=1−β1tmt(23)
ν
^
t
=
ν
t
1
−
β
2
t
(
24
)
\hat \nu_{t} = \frac{\nu_{t}}{1 - \beta_2^t} \qquad (24)
ν^t=1−β2tνt(24)
至此,生成Adam的参数更新公式如下:
θ
t
+
1
=
θ
t
−
η
ν
^
t
+
ϵ
m
^
t
(
25
)
\theta_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{\hat\nu_{t}} + \epsilon}\hat m_{t} \qquad (25)
θt+1=θt−ν^t+ϵηm^t(25)
Adam作者建议β1
、β2
分别取默认值0.9、0.999就好,ϵ为10−8。
从经验上来看,Adam在实际任务中表现更好(哈哈,其他人的经验)。
通过上面对Adam的理解,可以看出来,Adam结合了Adagrad善于处理稀疏梯度和Momentum善于处理非平稳目标的优点,相较于其他几种优化器效果更好。
2.2.7 AdaMax
AdaMax优化算法是对Adam算法的更新。
Adam算法中,使用到了参数的指数衰减的梯度平方的平均,即:
ν
t
=
β
2
ν
t
−
1
+
(
1
−
β
2
)
∣
g
t
∣
2
(
26
)
\nu_t = \beta_2 \nu_{t-1} + (1-\beta_2)|g_{t}|^2 \qquad (26)
νt=β2νt−1+(1−β2)∣gt∣2(26)
对上面的公式进行扩展到ℓp
范数,同时也将β2
扩展到βp2
,上面公式变为:
ν
t
=
β
2
p
ν
t
−
1
+
(
1
−
β
2
p
)
∣
g
t
∣
p
(
27
)
\nu_t = \beta_2^p \nu_{t-1} + (1-\beta_2^p)|g_{t}|^p \qquad (27)
νt=β2pνt−1+(1−β2p)∣gt∣p(27)
在这里,AdaMax用到了范数的相关形性质,即通常大p
值的范数通常具有数值不稳定性,因此我们更常见到的是1范数和2范数,但是无穷范数除外,当p
趋于无穷时,范数具有较好的数值稳定性。
因此,AdaMax的作者提出了使用无穷范数的AdaMax优化算法,并且使用了ℓ∞
的vt
能够收敛到一个外稳定的值,为了避免和上面的Adam优化算法搞混淆,我们使用ut
来代替vt
作为参数更新的表示:
u
t
=
β
2
∞
ν
t
−
1
+
(
1
−
β
2
∞
)
∣
g
t
∣
∞
u_t = \beta_2^{\infty} \nu_{t-1} + (1-\beta_2^{\infty})|g_{t}|^{\infty}
ut=β2∞νt−1+(1−β2∞)∣gt∣∞
=
m
a
x
(
β
2
ν
t
−
1
,
∣
g
t
∣
)
(
28
)
= max(\beta_2\nu_{t-1}, |g_{t}|) \qquad (28)
=max(β2νt−1,∣gt∣)(28)
根据上面的参数更新向量放到前面Adam的参数更新公式中,即为:
θ
t
+
1
=
θ
t
−
η
u
t
m
^
t
(
29
)
\theta_{t+1} = \theta_{t} - \frac{\eta}{u_{t}}\hat m_{t} \qquad (29)
θt+1=θt−utηm^t(29)
对公式(28)中,由于取的是最大值的计算操作,因此不用像在Adam中担心参数更新量趋近于0的问题,因此在AdaMax中也不需要进行偏差矫正的操作。
AdaMax中的超参数,一般比较好的默认是η=0.002
、β1=0.9
、β2=0.999
。
2.2.8 Nadam-加速自适应矩估计
Adam算法结合了RMSprop优化算法和动量优化算法的优点:
- RMSprop产生指数衰减的平方梯度的均值vt;
- 动量算法产生指数衰减的平方梯度的均值mt。
在上面介绍到的各种优化算法中,我们可以看到NAG算法优于动量优化算法。
基于此,Nadam结合了Adam算法和NAG算法,为了能够将NAG算法应用于Adam公式中,我们需要修改NAG算法的动量部分mt。
这里我们再来看下动量算法、NAG的对动量的改进算法的逻辑:
先是动量优化算法-Momentum:
g
t
=
▽
θ
J
(
θ
)
(
30
)
g_{t} = \bigtriangledown_{\theta} J(\theta) \qquad (30)
gt=▽θJ(θ)(30)
m
t
=
γ
m
t
−
1
+
η
g
t
(
31
)
m_{t} = \gamma m_{t-1} + \eta g_{t} \qquad (31)
mt=γmt−1+ηgt(31)
θ
t
+
1
=
θ
t
−
m
t
(
32
)
\theta_{t+1} = \theta_{t} - m_{t} \qquad (32)
θt+1=θt−mt(32)
将公式(31)带入公式(32)得到如下:
θ
t
+
1
=
θ
t
−
(
γ
m
t
−
1
+
η
g
t
)
(
33
)
\theta_{t+1} = \theta_{t} - (\gamma m_{t-1} + \eta g_{t}) \qquad (33)
θt+1=θt−(γmt−1+ηgt)(33)
从公式(33)容易看出,Momentum优化算法包括在历史累积梯度方向上前进一步、在当前梯度方向上前进一步。
再是NAG加速动量优化算法:
g
t
=
▽
θ
J
(
θ
−
γ
m
t
−
1
)
(
34
)
g_{t} = \bigtriangledown_{\theta} J(\theta - \gamma m_{t-1}) \qquad (34)
gt=▽θJ(θ−γmt−1)(34)
m
t
=
γ
m
t
−
1
+
η
g
t
(
35
)
m_{t} = \gamma m_{t-1} + \eta g_{t} \qquad (35)
mt=γmt−1+ηgt(35)
θ
t
+
1
=
θ
t
−
m
t
(
36
)
\theta_{t+1} = \theta_{t} - m_{t} \qquad (36)
θt+1=θt−mt(36)
NAG算法在计算梯度前就先使用动量步骤来更新参数,因此NAG跟Momentum的区别就是计算梯度gt上的差别。
基于上面两个基本的动量方向的优化算法的逻辑,引出Nadam算法:
相比于NAG算法的有两个使用动量的步骤-其一是更新梯度gt,其二是更新参数θt+1,我们现在使用look-ahead方式的动量直接更新当前参数:
g
t
=
▽
θ
J
(
θ
)
(
37
)
g_{t} = \bigtriangledown_{\theta} J(\theta) \qquad (37)
gt=▽θJ(θ)(37)
m
t
=
γ
m
t
−
1
+
η
g
t
(
38
)
m_{t} = \gamma m_{t-1} + \eta g_{t} \qquad (38)
mt=γmt−1+ηgt(38)
θ
t
+
1
=
θ
t
−
(
γ
m
t
+
η
g
t
)
(
39
)
\theta_{t+1} = \theta_{t} - (\gamma m_{t} + \eta g_{t}) \qquad (39)
θ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} = \beta_1 m_{t-1} + (1-\beta_1) g_{t} \qquad (40)
mt=β1mt−1+(1−β1)gt(40)
m
^
t
=
m
t
1
−
β
1
t
(
41
)
\hat m_{t} = \frac{m_{t}}{1 - \beta_1^t} \qquad (41)
m^t=1−β1tmt(41)
θ
t
+
1
=
θ
t
−
η
ν
t
2
+
ϵ
m
^
t
(
42
)
\theta_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{\nu_{t}^2} + \epsilon}\hat m_{t} \qquad (42)
θt+1=θt−νt2+ϵηm^t(42)
将上面公式(41)中的mt
带入得到公式(42)的展开式如下:
θ
t
+
1
=
θ
t
−
η
ν
t
2
+
ϵ
(
β
1
m
t
−
1
1
−
β
1
t
+
(
1
−
β
1
)
g
t
1
−
β
1
t
)
(
43
)
\theta_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{\nu_{t}^2} + \epsilon}(\frac{\beta_1 m_{t-1}}{1 - \beta_1^t} + \frac{(1-\beta_1) g_{t}}{1 - \beta_1^t}) \qquad (43)
θt+1=θt−νt2+ϵη(1−β1tβ1mt−1+1−β1t(1−β1)gt)(43)
β
1
m
t
−
1
1
−
β
1
t
(
44
)
\frac{\beta_1 m_{t-1}}{1 - \beta_1^t} \qquad (44)
1−β1tβ1mt−1(44)
β
1
m
t
−
1
1
−
β
1
t
−
1
(
45
)
\frac{\beta_1 m_{t-1}}{1 - \beta_1^{t-1}} \qquad (45)
1−β1t−1β1mt−1(45)
上面的公式(44)模块为上一步骤的动量估计的偏差修正,尽管公式(45)才是准确的对于上一步骤的动量估计的偏差修正,但是为了简单起见,此处我们忽略掉公式(44)和(45)在分母上的区别,所以公式(43)可以转化为:
θ
t
+
1
=
θ
t
−
η
ν
t
2
+
ϵ
(
β
1
m
^
t
−
1
+
(
1
−
β
1
)
g
t
1
−
β
1
t
)
(
46
)
\theta_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{\nu_{t}^2} + \epsilon}({\beta_1 \hat m_{t-1}} + \frac{(1-\beta_1) g_{t}}{1 - \beta_1^t}) \qquad (46)
θt+1=θt−νt2+ϵη(β1m^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}({\beta_1 \hat m_{t}} + \frac{(1-\beta_1) g_{t}}{1 - \beta_1^t}) \qquad (46)
θt+1=θt−νt2+ϵη(β1m^t+1−β1t(1−β1)gt)(46)
2.2.9 Lookahead
Geoffrey Hinton 的研究团队近期刚发表出来一篇 Lookahead 优化算法,大佬的研究成果自然要多关注呀,毕竟站在巨人的肩膀上。这周会算法核心内容更新进来。。。敬请期待!