优化算法
在深度学习领域,优化算法的选择是重中之重。梯度下降算法是目前神经网络中使用最广泛的优化算法之一。为了弥补朴素梯度下降GD的缺陷,又出现了SGD、SGD with Momentum、Adam、NAdam等。
深度学习优化算法经历了SGD->SGDM->NAG->AdaGrad->AdaDelta->Adam->Nadam 这样的发展历程。
1、梯度下降
见机器学习笔记一——常用优化算法—GD、BGD、SCD、MBGD
2、梯度下降优化算法-着手点
从上面的三种梯度下降法,我们可知道影响梯度下降算法的主要因素有
- 批量大小K
- 学习率 α \alpha α
- 梯度估计
因此,我们可以从三这方面下手,建立梯度下降优化算法
以下为深度学习常用优化算法
2.1 批量大小的选择
\quad \quad 在小批量梯度下降法中,批量大小对网络优化的影响也非常大。一般而言,批量大小不影响随机梯度的期望,但是会影响随机梯度的方差。
- 批量大小越大,随机梯度的方差越小,引入的噪声也越小,训练也越稳定,因此可以设置较大的学习率。
- 而批量大小较小时,需要设置较小的学习率,否则模型不会收敛。学习率通常要随着批量大小的增大而相应的增大。
- 一个简单有效的方法是线性缩放规则:当批量大小增加m倍时,学习率也增加m倍。线性缩放规则往往在批量大小比较小时适用,当批量大小比较大时,线性缩放会使得训练不稳定。
\quad \quad 如下图所示,给出了从回合(Epoch) 和 迭代(Iteration的角度,批量大小对损失下降的影响.每一次小批量更新为一次迭代,所有训练集的样本更新一遍为一个回合,两者的关系为
\quad \quad
分析上图可以看出,批量大小越大,下降效果越明显,并且下降曲线越平滑.但从图7.3b可以看出,如果按整个数据集上的回合(Epoch)数来看,则是批量样本数越小,适当小的批量大小会导致更快的收敛.
\quad \quad
此外,批量大小和模型的泛化能力也有一定的关系:
- 批量越大,越有可能收敛到尖锐最小值;
- 批量越小,越有可能收敛到平坦最小值。
记训练数据集的大小为m,两个极端情况
1)当min-batch的大小为m时,其实也就是batch梯度下降法。
2)当min-batch的大小为1时,其实也就是随机梯度下降法。
2.2 学习率调整
\quad \quad
学习率是神经网络优化时的重要超参数.如上图所示,学习率正好时,参数 x会沿着梯度方向不断更新,直至全局最优;学习率过大可能会造成 x 迈过(overshoot)最优解,甚至不断发散而无法收敛。从经验上来看,学习率在训练开始阶段要保持相对大些,从而保证收敛速度,在训练后期模型收敛到最优点附近时,学习率要设小一些,从而避免来回震荡。所以,实践中我们经常随着训练的不断进行而逐渐减小学习率。
\quad \quad
常用的学习率调整方法包括学习率衰减、学习率预热、周期性学习率调整以及一些自适应调整学习率的方法,比如 AdaGrad、RMSprop、AdaDelta 等.自适应学习率方法可以针对每个参数设置不同的学习率.
2.2.1 学习率衰减
\quad \quad 学习率衰减(Learning Rate Decay),也称为学习率退火(Learning Rate Annealing)。不失一般性,这里的衰减方式设置为按迭代次数进行衰减.
\quad \quad 假设初始化学习率为 α 0 \alpha_0 α0,在第𝑡 次迭代时的学习率 α t \alpha_t αt.常见的衰减方法有以下几种:
分段常数衰减(Piecewise Constant Decay):
\quad \quad 每经过 T 1 , T 2 , . . . , T m T_1,T_2,...,T_m T1,T2,...,Tm 次迭代将学习率衰减为原来的 β 1 , β 2 , . . . , β m \beta_1,\beta_2,...,\beta_m β1,β2,...,βm倍,其中 T m T_m Tm 和 β m \beta_m βm < 1 为根据经验设置的超参数。分段常数衰减也称为阶梯衰减。
逆时衰减(Inverse Time Decay):
α
t
=
α
0
1
1
+
β
∗
t
\alpha_t=\alpha_0\frac{1}{1+\beta*t}
αt=α01+β∗t1
\quad \quad
其中
β
\beta
β为衰减率
指数衰减(Exponential Decay):
α t = α 0 β t \alpha_t=\alpha_0\beta^t αt=α0βt
\quad \quad 其中 β < 1 \beta<1 β<1为衰减率
自然指数衰减(Natural Exponential Decay):
α
t
=
α
0
e
x
p
(
−
β
∗
t
)
\alpha_t=\alpha_0exp(-\beta*t)
αt=α0exp(−β∗t)
\quad \quad
其中
β
\beta
β为衰减率
余弦衰减(Cosine Decay):
α
t
=
1
2
α
0
(
1
+
c
o
s
(
t
π
T
)
)
\alpha_t=\frac{1}{2}\alpha_0(1+cos(\frac{t\pi}{T}))
αt=21α0(1+cos(Ttπ))
\quad \quad
其中T为总的迭代次数。
2.2.2 学习率预热
\quad \quad 在小批量梯度下降法中,当批量大小的设置比较大时,通常需要比较大的学习率.但在刚开始训练时,由于参数是随机初始化的,梯度往往也比较大,再加上比较大的初始学习率,会使得训练不稳定.
\quad \quad 为了提高训练稳定性,我们可以在最初几轮迭代时,采用比较小的学习率,等梯度下降到一定程度后再恢复到初始的学习率,这种方法称为学习率预热(Learning Rate Warmup).
\quad \quad
一个常用的学习率预热方法是逐渐预热(Gradual Warmup):
\quad \quad
假设预热的迭代次数为
T
′
T'
T′,初始学习率为
α
0
\alpha_0
α0,在预热过程中,每次更新的学习率为
α
t
′
=
t
T
′
α
0
,
1
≤
t
≤
T
′
\alpha_t^{'}=\frac{t}{T'}\alpha_0,\quad 1\leq t \leq T'
αt′=T′tα0,1≤t≤T′
\quad \quad
当预热过程结束,再选择一种学习率衰减方法来逐渐降低学习率。
2.2.3 周期性学习率调整
\quad \quad 为了使得梯度下降法能够逃离鞍点或尖锐最小值,一种经验性的方式是在训练过程中周期性地增大学习率.当参数处于尖锐最小值附近时,增大学习率有助于逃离尖锐最小值;当参数处于平坦最小值附近时,增大学习率依然有可能在该平坦最小值的吸引域(Basin of Attraction)内.因此,周期性地增大学习率虽然可能短期内损害优化过程,使得网络收敛的稳定性变差,但从长期来看有助于找到更好的局部最优解.
\quad \quad 两种常用的周期性调整学习率的方法:循环学习率和带热重启的随机梯度下降.
循环学习率:
\quad \quad
一种简单的方法是使用循环学习率(Cyclic Learning Rate),即让学习率在一个区间内周期性地增大和缩小.通常可以使用线性缩放来调整学习率,称为三角循环学习率(Triangular Cyclic Learning Rate).
\quad \quad
假设每个循环周期的长度相等都为 2Δ𝑇,其中前 Δ𝑇 步为学习率线性增大阶段,后Δ𝑇 步为学习率线性缩小阶段.在第𝑡 次迭代时,其所在的循环周期数𝑚为
带热重启的随机梯度下降:
\quad \quad
带热重启的随机梯度下降是用热重启方式来替代学习率衰减的方法.学习率每间隔一定周期后重新初始化为某个预先设定值,然后逐渐衰减.每次重启后模型参数不是从头开始优化,而是从重启前的参数基础上继续优化.
2.3 梯度估计修正
\quad \quad 损失函数有关自变量的梯度代表了损失函数在自变量当前位置下降最快的方向。因此,梯度下降也叫作最陡下降。在每次迭代中,梯度下降根据自变量当前位置,沿着当前位置的梯度更新自变量,然而,如果自变量的迭代方向仅仅取决于自变量当前位置,可能会带来一些问题。
\quad \quad
例如:损失函数为
f
(
x
)
=
0.1
x
1
2
+
2
x
2
2
f(x)=0.1x_1^2+2x_2^2
f(x)=0.1x12+2x22
该函数在
x
1
,
x
2
x_1,x_2
x1,x2的斜率相差较大,如果给定学习率,梯度下降迭代自变量时,会使自变量在
x
2
x_2
x2比在
x
1
x_1
x1的移动幅度更大,可能会越过最优解;如果降低学习率,会造成在
x
1
x_1
x1方向上朝最优解移动缓慢,收敛速度变慢。下面实现基于这个目标函数的梯度下降,并演示使用学习率为 0.4 时自变量的迭代轨迹。
%matplotlib inline
import numpy as np
eta = 0.4#学习率
def f_2d(x1, x2):# 目标函数
return 0.1 * x1 ** 2 + 2 * x2 ** 2
def gd_2d(x1, x2):
return (x1 - eta * 0.2 * x1, x2 - eta * 4 * x2)
def train_2d(trainer):
x1, x2 = -5, -2 # 初始化自变量x1,x2
results = [(x1, x2)]
for i in range(20):
x1,x2= trainer(x1,x2)
results.append((x1, x2))
print('epoch %d, x1 %f, x2 %f' % (i + 1, x1, x2))
return results
def show_trace_2d(f, results): # 画轨迹
plt.plot(*zip(*results), '-o', color='#ff7f0e')
x1, x2 = np.meshgrid(np.arange(-5.5, 1.0, 0.1), np.arange(-3.0, 1.0, 0.1))
plt.contour(x1, x2, f(x1, x2), colors='#1f77b4')
plt.xlabel('x1')
plt.ylabel('x2')
show_trace_2d(f_2d, train_2d(gd_2d))
可以看到,同一位置上,目标函数在竖直方向(
x
2
x_2
x2轴方向)比在水平方向(
x
1
x_1
x1轴方向)的斜率的绝对值更大。因此,给定学习率,梯度下降迭代自变量时会使自变量在竖直方向比在水平方向移动幅度更大。那么,我们需要一个较小的学习率从而避免自变量在竖直方向上越过目标函数最优解。然而,这会造成自变量在水平方向上朝最优解移动变慢。
下面我们试着将学习率调得稍大一点,此时自变量在竖直方向不断越过最优解并逐渐发散。
eta = 0.6
show_trace_2d(f_2d, train_2d(gd_2d))
\quad \quad
从上面两张图可以看出,仅仅根据当前位置的梯度更新自变量,还是存在一定的缺陷:随机梯度下降方法中每次迭代的梯
度估计和整个训练集上的最优梯度并不一致,具有一定的随机性. (增加批量大小也是缓解随机性的一种方式.),为了解决上述梯度下降的问题,提出了梯度估计修正的想法:使用最近一段时间内的平均梯度来代替当前时刻的随机梯度来作为参数更新的方向,从而提高优化速度。在此基础上,运用最多的是动量法和Nesterov加速梯度下降法。
3、各种优化算法
为了更有效的训练神经网络,在标准的小批量梯度下降法的基础上,也经常使用一些改进方法以加快优化速度,比如如何选择批量大小、如何调整学习率以及如何修正梯度估计。当然,这些改进方法同样适用于批量或随机梯度下降法上。
优化算法的主要区别在于怎么调节学习率和动量 (本质上还是调节的梯度–>可正可负)
几个定义介绍如下:
θ
\theta
θ:待优化参数
Δ
θ
t
\Delta \theta_t
Δθt:每次迭代时参数更新的差值,定义如下:
Δ
θ
t
=
θ
t
−
θ
t
−
1
\Delta \theta_t=\theta_t-\theta_{t-1}
Δθt=θt−θt−1
θ
t
=
θ
t
−
1
+
Δ
θ
t
\theta_t=\theta_{t-1}+\Delta\theta_{t}
θt=θt−1+Δθt:参数
θ
\theta
θ的更新公式
基于梯度估计修正产生的梯度下降优化算法
3.1 动量法 (Momentum)
\quad \quad 动量法的提出是为了解决梯度下降的上述问题(梯度估计的随机性)。动量法 (Momentum),又称动量梯度下降法是用之前积累动量来替代真正的梯度。每次迭代的梯度可以看作加速度。
\quad \quad 动量法对每次迭代的步骤做如下修改:
\quad \quad
在第𝑡 次迭代时,计算负梯度
的 “加权移动平均” 即速度变量作为参数的更新方向,
Δ
θ
t
=
β
Δ
θ
t
−
1
−
α
g
t
=
−
α
∑
τ
=
1
t
β
t
−
τ
g
τ
\Delta \theta_t=\beta \Delta \theta_{t-1}-\alpha g_t=-\alpha \sum_{\tau=1}^t\beta^{t-\tau}g_\tau
Δθt=βΔθt−1−αgt=−ατ=1∑tβt−τgτ
参数
θ
t
\theta_t
θt的更新公式为:
θ
t
=
θ
t
−
1
+
Δ
θ
t
\theta_t=\theta_{t-1}+\Delta \theta_t
θt=θt−1+Δθt
\quad \quad 其中 β \beta β为动量因子( β \beta β满足 0 ≤ β < 1 ) 0 \leq \beta < 1) 0≤β<1),通常设为0.9; 当 β = 0 \beta=0 β=0 时,动量法等价于梯度下降。 α \alpha α为学习率, g t g_t gt为当前时刻t的梯度(可以为三种梯度下降法的任意一种,深度学习一般使用小批量梯度下降法比较多,因此后续讨论将沿用“小批量随机梯度下降”一节中时间步 t t t的小批量随机梯度 g t \boldsymbol{g}_t gt的定义)
- 每个参数的实际更新差值取决于最近一段时间内梯度的加权平均值.
- 当某个参数在最近一段时间内的梯度方向不一致时,其真实的参数更新幅度变小;
- 相反,当在最近一段时间内的梯度方向都一致时,其真实的参数更新幅度变大,起到加速作用.
- 一般而言,在迭代初期,梯度方向都比较一致,动量法会起到加速作用,可以更快地到达最优点.在迭代后期,梯度方向会不一致,在收敛值附近振荡,动量法会起到减速作用,增加稳定性.从某种角度来说,当前梯度叠加上部分的上次梯度,一定程度上可以近似看作二阶梯度.
3.1.1 动量法原理-指数加权移动平均
为了从数学上理解动量法,让我们先解释一下指数加权移动平均。另外,神经网络中的常用优化算法都会涉及到指数加权移动平均。
1、概述:
指数加权移动平均(Exponential Weighted Moving Average),也叫指数加权平均,简称EWMA。
- 算术平均(权重相等)—>加权平均(权重不等)—>移动平均(大约是只取最近的N次数据进行计算)—> 批量归一化(BN)及各种优化算法的基础
- EWMA:是以指数式递减加权的移动平均,各数值的加权随时间而指数式递减,越近期的数据加权越重,影响力越大,但较旧的数据也给予一定的加权。
2、定义:
EWMA通过将历史的值和当前一实际值进行加权求和来得到当前值的估计,常用于减小序列数据的噪声,其公式如下:
给定超参数 0 ≤ β < 1 0 \leq \beta < 1 0≤β<1,当前时间 t t t的变量 y t y_t yt是上一时间 t − 1 t-1 t−1的变量 y t − 1 y_{t-1} yt−1和当前时间另一实际变量 x t x_t xt的线性组合:
y t = β y t − 1 + ( 1 − β ) x t . y_t = \beta y_{t-1} + (1-\beta) x_t. yt=βyt−1+(1−β)xt.
3、意义
我们可以对 y t y_t yt展开:
y t = ( 1 − β ) x t + β y t − 1 = ( 1 − β ) x t + ( 1 − β ) ⋅ β x t − 1 + β 2 y t − 2 = ( 1 − β ) x t + ( 1 − β ) ⋅ β x t − 1 + ( 1 − β ) ⋅ β 2 x t − 2 + β 3 y t − 3 … \begin{aligned} y_t &= (1-\beta) x_t + \beta y_{t-1}\\ &= (1-\beta)x_t + (1-\beta) \cdot \beta x_{t-1} + \beta^2y_{t-2}\\ &= (1-\beta)x_t + (1-\beta) \cdot \beta x_{t-1} + (1-\beta) \cdot \beta^2x_{t-2} +\beta^3y_{t-3}\\ &\ldots \end{aligned} yt=(1−β)xt+βyt−1=(1−β)xt+(1−β)⋅βxt−1+β2yt−2=(1−β)xt+(1−β)⋅βxt−1+(1−β)⋅β2xt−2+β3yt−3…
- 令 n = 1 / ( 1 − β ) n = 1/(1-\beta) n=1/(1−β),那么 ( 1 − 1 / n ) n = β 1 / ( 1 − β ) \left(1-1/n\right)^n = \beta^{1/(1-\beta)} (1−1/n)n=β1/(1−β)。因为
lim n → ∞ ( 1 − 1 n ) n = exp ( − 1 ) ≈ 0.3679 , \lim_{n \rightarrow \infty} \left(1-\frac{1}{n}\right)^n = \exp(-1) \approx 0.3679, n→∞lim(1−n1)n=exp(−1)≈0.3679,
- 故当 β → 1 \beta \rightarrow 1 β→1时, β 1 / ( 1 − β ) = e − 1 \beta^{1/(1-\beta)}=e^{-1} β1/(1−β)=e−1,如 0.9 5 20 ≈ e − 1 0.95^{20} \approx e^{-1} 0.9520≈e−1。
- 如果把 e − 1 e^{-1} e−1当作一个比较小的数,我们可以在近似中忽略所有含 β 1 / ( 1 − β ) \beta ^{1/(1-\beta )} β1/(1−β)和比 β 1 / ( 1 − β ) \beta ^{1/(1-\beta )} β1/(1−β)更高阶的系数的项。例如,当 β = 0.95 \beta =0.95 β=0.95时, 1 1 − β = 20 \frac{1}{1-\beta }=20 1−β1=20, β 20 + \beta ^{20+} β20+就很小,可以将大于等于 β 20 \beta ^{20} β20阶数的项去掉,则
y t ≈ 0.05 ∑ i = 0 19 0.9 5 i x t − i . y_t \approx 0.05 \sum_{i=0}^{19} 0.95^i x_{t-i}. yt≈0.05i=0∑190.95ixt−i.
- 因此,在实际中,我们常常将
y
t
y_t
yt看作是对最近
1
/
(
1
−
β
)
1/(1-\beta )
1/(1−β)个时间步的
x
t
x_t
xt值的加权平均。 即我们可以每次只考虑最近
N
=
1
1
−
β
N=\frac{1}{1-\beta}
N=1−β1天的数据来计算当前时刻的EWMA,这就是
移动平均
的来源。 - 例如,当 β = 0.95 \beta = 0.95 β=0.95时, y t y_t yt可以被看作对最近20个时间步的 x t x_t xt值的加权平均;当 β = 0.9 \beta = 0.9 β=0.9时, y t y_t yt可以看作是对最近10个时间步的 x t x_t xt值的加权平均。而且,离当前时间步 t t t越近的 x t x_t xt值获得的权重越大(越接近1)。
4、EWMA 的优点
-
它占用极少内存:计算指数加权平均数只占用单行数字的存储和内存,然后把最新数据代入公式,不断覆盖就可以了。
-
移动平均线能较好的反应时间序列的变化趋势,权重的大小不同起到的作用也是不同,时间比较久远的变量值的影响力相对较低,时间比较近的变量值的影响力相对较高。
下面是吴恩达课程对移动平均指数理解的一个例子:温度的例子来详细介绍一下。
以伦敦的气温为例:
当前温度的指数移动平均值:
ν
t
=
β
ν
t
−
1
+
(
1
−
β
)
θ
t
\nu_t=\beta \nu_{t-1}+(1-\beta)\theta_t
νt=βνt−1+(1−β)θt
- θ t \theta_t θt为当前t时刻的实际温度;系数 β \beta β表示加权下降的快慢,值越小权重下降的越快; ν t \nu_t νt为t时刻EWMA的值。
- 当
ν
0
=
0
\nu_0=0
ν0=0时,
ν
t
=
(
1
−
β
)
(
θ
t
+
β
θ
t
−
1
+
β
2
θ
t
−
2
+
.
.
.
+
β
t
−
1
θ
1
)
\nu_t=(1-\beta)(\theta_t+\beta \theta_{t-1}+\beta^2 \theta_{t-2}+...+\beta^{t-1} \theta_1)
νt=(1−β)(θt+βθt−1+β2θt−2+...+βt−1θ1),从公式中可以看出:每天温度(
θ
\theta
θ)的权重系数以
指数等比形式
缩小,时间越靠近当前时刻的数据加权影响力越大。 - 在优化算法中,我们一般取 β ≥ 0.9 \beta \geq 0.9 β≥0.9,而 1 + β + β 2 + . . . + β t − 1 = 1 − β t 1 − β 1+\beta+\beta^2+...+\beta^{t-1}=\frac{1-\beta^t}{1-\beta} 1+β+β2+...+βt−1=1−β1−βt,所以当t足够大时 β t ≈ 0 \beta^t\approx0 βt≈0,此时便是严格意义上的指数加权移动平均。
- 在优化算法中,我们一般取
β
≥
0.9
\beta \geq 0.9
β≥0.9,此时有
β
1
1
−
β
≈
1
e
≈
0.36
\beta^{\frac{1}{1-\beta}}\approx \frac{1}{e}\approx0.36
β1−β1≈e1≈0.36,也就是说
N
=
1
1
−
β
N=\frac{1}{1-\beta}
N=1−β1天后,曲线的高度下降到了约原来的
1
3
\frac{1}{3}
31,由于时间越往前推移
θ
\theta
θ权重越来越小。所以我们可以每次只考虑最近
N
=
1
1
−
β
N=\frac{1}{1-\beta}
N=1−β1天的数据来计算当前时刻的EWMA,这就是
移动平均
的来源。
由上面的分析可将 ν t \nu_t νt看作是最近 1 1 − β \frac{1}{1-\beta} 1−β1天的平均温度。
红色: β = 0.9 \beta=0.9 β=0.9, 1 1 − β = 1 1 − 0.9 = 10 \frac{1}{1-\beta}=\frac{1}{1-0.9}=10 1−β1=1−0.91=10
当前温度是以最近十天的加权平均值,而做出的温度变化轨迹。
红色曲线,比起绿线和黄线更好的平均了温度,效果更好。
绿色: β = 0.98 \beta=0.98 β=0.98, 1 1 − β = 1 1 − 0.98 = 50 \frac{1}{1-\beta}=\frac{1}{1-0.98}=50 1−β1=1−0.981=50
当前温度是以最近五十天的加权平均值,而做出的温度变化轨迹。
这就是粗略平均了一下,过去50天的温度,这时作图可以得到绿线。这个高值要注意几点,你得到的曲线要平坦一些,原因在于你多平均了几天的温度,所以这个曲线,波动更小,更加平坦,缺点是曲线进一步右移,因为现在平均的温度值更多,要平均更多的值,指数加权平均公式在温度变化时,适应地更缓慢一些,所以会出现一定延迟,因为当 β = 0.98 \beta=0.98 β=0.98,相当于给前一天的值加了太多权重,只有0.02的权重给了当日的值,所以温度变化时,温度上下起伏,当 β = 0.98 \beta=0.98 β=0.98较大时,指数加权平均值适应地更缓慢一些。
黄色:
β
=
0.5
\beta=0.5
β=0.5,
1
1
−
β
=
1
1
−
0.5
=
2
\frac{1}{1-\beta}=\frac{1}{1-0.5}=2
1−β1=1−0.51=2
当前温度是以最近两天的加权平均值,而做出的温度变化轨迹。
这是平均了两天的温度。由于仅平均了两天的温度,平均的数据太少,所以得到的曲线有更多的噪声,有可能出现异常值,但是这个曲线能够更快适应温度变化。
3.1.2 EWMA 在 Momentum 优化算法中应用的理解
现在,我们对动量法的速度变量即梯度变量做变形:
Δ θ t ← β Δ θ t − 1 − ( 1 − β ) ( α 1 − β g t ) . \Delta \theta_t \leftarrow \beta\Delta \theta_{t-1} -(1 - \beta) \left(\frac{\alpha}{1 - \beta} \boldsymbol{g}_t\right). Δθt←βΔθt−1−(1−β)(1−βαgt).
- 由指数加权移动平均的形式可得,梯度变量 Δ θ t \Delta \theta_t Δθt实际上对序列 { − α g t − i / ( 1 − β ) : i = 0 , … , 1 / ( 1 − β ) − 1 } \{-\alpha\boldsymbol{g}_{t-i} /(1-\beta):i=0,\ldots,1/(1-\beta)-1\} {−αgt−i/(1−β):i=0,…,1/(1−β)−1}做了指数加权移动平均。
- 换句话说,相比于小批量随机梯度下降,动量法在每个时间步的自变量更新量近似于将前者对应的最近 1 / ( 1 − β ) 1/(1-\beta) 1/(1−β)个时间步的更新量做了指数加权移动平均后再除以 1 − β 1-\beta 1−β。
- 所以,在动量法中,自变量在各个方向上的移动幅度不仅取决于当前梯度,还取决于过去的各个梯度在各个方向上是否一致。
- 在某个时间段内一些参数的梯度方向与之前的不一致时,那么真实的参数更新幅度会变小;相反,若在某个时间段内的参数的梯度方向都一致,那么其真实的参数更新幅度会变大,起到加速收敛的作用。在迭代后期,由于随机噪声问题,经常会在收敛值附近震荡,动量法会起到减速作用,增加稳定性。
3.2 Nesterov加速梯度下降法
\quad \quad Nesterov 加速梯度(Nesterov Accelerated Gradient,NAG)是一种对动量法的改进,也称为Nesterov动量法(Nesterov Momentum)。
\quad \quad
在动量法中,实际的参数更新方向
Δ
θ
t
\Delta \theta_t
Δθt为上一步的参数更新方向
Δ
θ
t
−
1
\Delta \theta_{t-1}
Δθt−1 和当前梯度的反方向
−
g
t
-\boldsymbol{g}_t
−gt 的叠加.这样,
Δ
θ
t
\Delta \theta_t
Δθt 可以被拆分为两步进行,先根据
Δ
θ
t
−
1
\Delta \theta_{t-1}
Δθt−1 更新一次得到参数
θ
^
\hat{\theta}
θ^,再用
−
g
t
-\boldsymbol{g}_t
−gt进行更新.
θ
^
=
θ
t
−
1
+
β
Δ
θ
t
−
1
θ
t
=
θ
^
−
α
g
t
\hat{\theta}=\theta_{t-1}+\beta\Delta \theta_{t-1}\\ \theta_t=\hat{\theta}-\alpha\boldsymbol{g}_t
θ^=θt−1+βΔθt−1θt=θ^−αgt
其中梯度
g
t
\boldsymbol{g}_t
gt为点
θ
t
−
1
\theta_{t-1}
θt−1上的梯度,因此在第二步更新中有些不太合理.更合理的更新方向应该为
θ
^
\hat{\theta}
θ^上的梯度.
这样,合并后的更新方向为
Δ
θ
t
=
β
Δ
θ
t
−
1
−
α
g
t
(
θ
t
−
1
+
β
Δ
θ
t
−
1
)
\Delta \theta_t= \beta\Delta \theta_{t-1}-\alpha \boldsymbol{g}_t (\theta_{t-1}+\beta\Delta \theta_{t-1})
Δθt=βΔθt−1−αgt(θt−1+βΔθt−1)
其中, g t ( θ t − 1 + β Δ θ t − 1 ) \boldsymbol{g}_t (\theta_{t-1}+\beta\Delta \theta_{t-1}) gt(θt−1+βΔθt−1)表示损失函数在点 θ ^ = θ t − 1 + β Δ θ t − 1 \hat{\theta}=\theta_{t-1}+\beta\Delta \theta_{t-1} θ^=θt−1+βΔθt−1上的偏导数。
图7.6给出了动量法和Nesterov加速梯度在参数更新时的比较.
基于学习率调整产生的梯度下降优化算法
在之前介绍过的优化算法中,目标函数自变量的每一个元素在相同时间步都使用同一个学习率来自我迭代。举个例子,假设目标函数为 f f f,自变量为一个二维向量 [ x 1 , x 2 ] ⊤ [x_1, x_2]^\top [x1,x2]⊤,该向量中每一个元素在迭代时都使用相同的学习率。例如,在学习率为 η \eta η的梯度下降中,元素 x 1 x_1 x1和 x 2 x_2 x2都使用相同的学习率 η \eta η来自我迭代:
x 1 ← x 1 − η ∂ f ∂ x 1 , x 2 ← x 2 − η ∂ f ∂ x 2 . x_1 \leftarrow x_1 - \eta \frac{\partial{f}}{\partial{x_1}}, \quad x_2 \leftarrow x_2 - \eta \frac{\partial{f}}{\partial{x_2}}. x1←x1−η∂x1∂f,x2←x2−η∂x2∂f.
在[“动量法”]一节里提到,当 x 1 x_1 x1和 x 2 x_2 x2的梯度值有较大差别时,需要选择足够小的学习率使得自变量在梯度值较大的维度上不发散。但这样会导致自变量在梯度值较小的维度上迭代过慢。动量法依赖指数加权移动平均使得自变量的更新方向更加一致,从而降低发散的可能。我们也可以从学习率调整这一方面着手:根据自变量在每个维度的梯度值的大小来调整各个维度上的学习率,从而避免统一的学习率难以适应所有维度的问题 。下面介绍几种自适应学习率算法。
3.3 Adagrad算法
\quad \quad AdaGrad算法是借鉴L2正则化的思想,每次迭代时自适应地调整每个参数的学习率。其方法会使用梯度 g t \boldsymbol{g}_t gt按元素平方的累加变量 s t \boldsymbol{s}_t st。在时间步0,AdaGrad将 s 0 \boldsymbol{s}_0 s0中每个元素初始化为0。
- 在时间步 t t t,首先将小批量随机梯度 g t \boldsymbol{g}_t gt按元素平方后累加到变量 s t \boldsymbol{s}_t st:
s t = s t − 1 + g t ⊙ g t , \boldsymbol{s}_t = \boldsymbol{s}_{t-1} + \boldsymbol{g}_t \odot \boldsymbol{g}_t, st=st−1+gt⊙gt,
其中 ⊙ \odot ⊙是按元素相乘。
- 接着,我们将目标函数自变量中每个元素的学习率通过按元素运算重新调整一下,得到参数更新差值为
Δ θ t = − α s t + ϵ ⊙ g t , \Delta \theta_t=- \frac{\alpha}{\sqrt{\boldsymbol{s}_t + \epsilon}} \odot \boldsymbol{g}_t, Δθt=−st+ϵα⊙gt,
- 参数更新:
θ t = θ t − 1 − α s t + ϵ ⊙ g t \theta_t =\theta_{t-1} - \frac{\alpha}{\sqrt{\boldsymbol{s}_t + \epsilon}} \odot \boldsymbol{g}_t θt=θt−1−st+ϵα⊙gt
其中 α \alpha α是学习率, ϵ \epsilon ϵ是为了维持数值稳定性而设置的非常小的常数,一般取值 e − 7 e^{-7} e−7到 e − 10 e^{-10} e−10。这里开方、除法和乘法的运算都是按元素运算的。这些按元素运算使得目标函数自变量中每个元素都分别拥有自己的学习率。
算法 4.3 AdaGrad 算法(用于小批量梯度下降)
输入:
\quad \quad 学习率 α \alpha α; 初始参数 θ 0 \theta_0 θ0;常数 ϵ \epsilon ϵ(通常为 e − 8 e^{-8} e−8);初始梯度累积变量 s 0 \boldsymbol{s}_0 s0为0
输出:
\quad \quad 参数 θ \theta θ
过程:
- 迭代:
- 从训练集中抽取包含m个样本 { x ( 1 ) , . . . , x ( m ) } \{x^{(1)},...,x^{(m)}\} {x(1),...,x(m)}的小批量,对应目标为 y ( i ) y^{(i)} y(i)
- 计算梯度: g t = 1 m ∂ J ( θ ) ∂ θ \boldsymbol{g}_t=\frac{1}{m}\frac{\partial J(θ)}{\partial \theta} gt=m1∂θ∂J(θ) J ( θ ) J(\theta) J(θ)为目标函数或代价函数。
- 累积平方梯度:
s t : = s t + g t ⊙ g t , \boldsymbol{s}_t := \boldsymbol{s}_{t} + \boldsymbol{g}_t \odot \boldsymbol{g}_t, st:=st+gt⊙gt,- 参数更新: θ t : = θ t − − α s t + ϵ ⊙ g t \theta_t:=\theta_t-- \frac{\alpha}{\sqrt{\boldsymbol{s}_t + \epsilon}} \odot \boldsymbol{g}_t θt:=θt−−st+ϵα⊙gt
- 终止:可设置最大迭代次数或梯度小于某值。
【代码实现】
特点:
- 在 AdaGrad 算法中,如果某个参数的偏导数累积比较大,其学习率相对较小;相反,如果其偏导数累积较小,其学习率相对较大.但整体是随着迭代次数的增加,学习率逐渐缩小.
- AdaGrad 算法的缺点是在经过一定次数的迭代依然没有找到最优点时,由于这时的学习率已经非常小,很难再继续找到最优点。
3.4 RMSprop算法
\quad \quad
RMSprop算法是Geoff Hinton提出的一种自适应学习率的方法,可以在有些情况下避免 AdaGrad 算法中学习率不断单调下降以至于过早衰减的缺点。
算法:
\quad \quad RMSProp算法首先将这些梯度按元素平方做指数加权移动平均。具体来说,给定超参数 0 ≤ β < 1 0 \leq \beta < 1 0≤β<1,RMSProp算法在时间步 t > 0 t>0 t>0计算
s t ← β s t − 1 + ( 1 − β ) g t ⊙ g t . \boldsymbol{s}_t \leftarrow \beta \boldsymbol{s}_{t-1} + (1 - \beta) \boldsymbol{g}_t \odot \boldsymbol{g}_t. st←βst−1+(1−β)gt⊙gt.
和AdaGrad算法一样,RMSProp算法将目标函数自变量中每个元素的学习率通过按元素运算重新调整,得到参数更新差值为
Δ θ t = − α s t + ϵ ⊙ g t , \Delta\theta_t = - \frac{\alpha}{\sqrt{\boldsymbol{s}_t + \epsilon}} \odot \boldsymbol{g}_t, Δθt=−st+ϵα⊙gt,
参数更新方式如下:
s
t
:
=
β
s
t
+
(
1
−
β
)
g
t
⊙
g
t
.
,
θ
t
:
=
θ
t
−
α
s
t
+
ϵ
⊙
g
t
\boldsymbol{s}_t := \beta \boldsymbol{s}_{t} + (1 - \beta) \boldsymbol{g}_t \odot \boldsymbol{g}_t.,\\ \theta_t :=\theta_{t} - \frac{\alpha}{\sqrt{\boldsymbol{s}_t + \epsilon}} \odot \boldsymbol{g}_t
st:=βst+(1−β)gt⊙gt.,θt:=θt−st+ϵα⊙gt
其中 α \alpha α是学习率, ϵ \epsilon ϵ是为了维持数值稳定性而设置的非常小的常数,一般取值 e − 7 e^{-7} e−7到 e − 10 e^{-10} e−10, β \beta β为衰减率,一般取值为0.9。
- 因为RMSProp算法的状态变量 s t \boldsymbol{s}_t st是对平方项 g t ⊙ g t \boldsymbol{g}_t \odot \boldsymbol{g}_t gt⊙gt的指数加权移动平均,所以可以看作最近 1 / ( 1 − β ) 1/(1-\beta) 1/(1−β)个时间步的小批量随机梯度平方项的加权平均。如此一来,自变量每个元素的学习率在迭代过程中就不再一直降低(或不变)。
- 从上式可以看出,RMSProp 算法和 AdaGrad 算法的区别在于 s t \boldsymbol{s}_t st 的计算由累积方式变成了指数衰减移动平均.在迭代过程中,每个参数的学习率并不是呈衰减趋势,既可以变小也可以变大.
3.5 AdaDelta算法
\quad \quad AdaDelta 算法也是 AdaGrad 算法的一个改进.和 RMSprop算法类似,AdaDelta 算法通过梯度平方的指数衰减移动平均来调整学习率.此外,AdaDelta算法还引入了每次参数更新差值Δ𝜃的平方的指数衰减权移动平均.
\quad \quad
第t次迭代时,参数更新差值
Δ
θ
\Delta\theta
Δθ的平方的指数衰减加权移动平均为
Δ
X
t
−
1
2
=
β
1
Δ
X
t
−
2
2
+
(
1
−
β
)
Δ
θ
t
−
1
⊙
Δ
θ
t
−
1
\Delta X_{t-1}^2=\beta_1 \Delta X_{t-2}^2+(1-\beta) \Delta\theta_{t-1}\odot\Delta\theta_{t-1}
ΔXt−12=β1ΔXt−22+(1−β)Δθt−1⊙Δθt−1
其中 β 1 \beta_1 β1为衰减率
\quad \quad
AdaDelta 算法的参数更新差值为
Δ
θ
t
=
−
Δ
X
t
−
1
2
+
ϵ
s
t
+
ϵ
g
t
\Delta \theta_t=-\frac{\sqrt {\Delta X_{t-1}^2+\epsilon}}{\sqrt{\boldsymbol{s}_t+\epsilon}}\boldsymbol{g}_t
Δθt=−st+ϵΔXt−12+ϵgt
其中,
s
t
=
β
s
t
−
1
+
(
1
−
β
)
g
t
⊙
g
t
.
\boldsymbol{s}_t = \beta \boldsymbol{s}_{t-1} + (1 - \beta) \boldsymbol{g}_t \odot \boldsymbol{g}_t.
st=βst−1+(1−β)gt⊙gt.
Δ
X
t
−
1
2
\Delta X_{t-1}^2
ΔXt−12为参数更新差值Δ𝜃 的指数衰减权移动平均.
\quad \quad 从上式可以看出,AdaDelta算法将RMSprop算法中的初始学习率𝛼改为动态计算的 Δ X t − 1 2 \sqrt {\Delta X_{t-1}^2} ΔXt−12,在一定程度上平抑了学习率的波动.
3.6 Adam 算法
\quad \quad Adam算法(Adaptive Moment Estimation Algorithm)可以看作动量法和 RMSprop 算法的结合,不但使用动量作为参数更新方向,而且可以自适应调整学习率。
\quad \quad
Adam算法使用了动量变量
v
t
\boldsymbol{v}_t
vt和RMSProp算法中小批量随机梯度按元素平方的指数加权移动平均变量
s
t
\boldsymbol{s}_t
st,并在时间步0将它们中每个元素初始化为0。
1)给定超参数
0
≤
β
1
<
1
0 \leq \beta_1 < 1
0≤β1<1(算法作者建议设为0.9),时间步
t
t
t的动量变量
v
t
\boldsymbol{v}_t
vt即小批量随机梯度
g
t
\boldsymbol{g}_t
gt的指数加权移动平均:
v t ← β 1 v t − 1 + ( 1 − β 1 ) g t . \boldsymbol{v}_t \leftarrow \beta_1 \boldsymbol{v}_{t-1} + (1 - \beta_1) \boldsymbol{g}_t. vt←β1vt−1+(1−β1)gt.
2)和RMSProp算法中一样,给定超参数 0 ≤ β 2 < 1 0 \leq \beta_2 < 1 0≤β2<1(算法作者建议设为0.999),将小批量随机梯度按元素平方后的项 g t ⊙ g t \boldsymbol{g}_t \odot \boldsymbol{g}_t gt⊙gt做指数加权移动平均得到 s t \boldsymbol{s}_t st:
s t = β 2 s t − 1 + ( 1 − β 2 ) g t ⊙ g t . \boldsymbol{s}_t =\beta_2 \boldsymbol{s}_{t-1} + (1 - \beta_2) \boldsymbol{g}_t \odot \boldsymbol{g}_t. st=β2st−1+(1−β2)gt⊙gt.
3)由于我们将 v 0 \boldsymbol{v}_0 v0和 s 0 \boldsymbol{s}_0 s0中的元素都初始化为0,在时间步 t t t我们得到 v t = ( 1 − β 1 ) ∑ i = 1 t β 1 t − i g i \boldsymbol{v}_t = (1-\beta_1) \sum_{i=1}^t \beta_1^{t-i} \boldsymbol{g}_i vt=(1−β1)∑i=1tβ1t−igi。将过去各时间步小批量随机梯度的权值相加,得到 ( 1 − β 1 ) ∑ i = 1 t β 1 t − i = 1 − β 1 t (1-\beta_1) \sum_{i=1}^t \beta_1^{t-i} = 1 - \beta_1^t (1−β1)∑i=1tβ1t−i=1−β1t。需要注意的是,当 t t t较小时,过去各时间步小批量随机梯度权值之和会较小。例如,当 β 1 = 0.9 \beta_1 = 0.9 β1=0.9时, v 1 = 0.1 g 1 \boldsymbol{v}_1 = 0.1\boldsymbol{g}_1 v1=0.1g1。为了消除这样的影响,对于任意时间步 t t t,我们可以将 v t \boldsymbol{v}_t vt再除以 1 − β 1 t 1 - \beta_1^t 1−β1t,从而使过去各时间步小批量随机梯度权值之和为1。这也叫作偏差修正。在Adam算法中,我们对变量 v t \boldsymbol{v}_t vt和 s t \boldsymbol{s}_t st均作偏差修正:
v ^ t = v t 1 − β 1 t , \hat{\boldsymbol{v}}_t = \frac{\boldsymbol{v}_t}{1 - \beta_1^t}, v^t=1−β1tvt,
s ^ t = s t 1 − β 2 t . \hat{\boldsymbol{s}}_t = \frac{\boldsymbol{s}_t}{1 - \beta_2^t}. s^t=1−β2tst.
3)接下来,Adam算法使用以上偏差修正后的变量 v ^ t \hat{\boldsymbol{v}}_t v^t和 s ^ t \hat{\boldsymbol{s}}_t s^t,定义参数更新差值为
Δ θ t = − α v ^ t s ^ t + ϵ , \Delta \theta_t =- \frac{\alpha \hat{\boldsymbol{v}}_t}{\sqrt{\hat{\boldsymbol{s}}_t+ \epsilon} }, Δθt=−s^t+ϵαv^t,
其中 α \alpha α是学习率,通常设为0.001,并且也可以进行衰减。 ϵ \epsilon ϵ是为了维持数值稳定性而添加的常数,如 1 0 − 8 10^{-8} 10−8。和AdaGrad算法、RMSProp算法以及AdaDelta算法一样,目标函数自变量中每个元素都分别拥有自己的学习率。
4) 最后,使用 Δ θ t \boldsymbol{\Delta\theta}_t Δθt更新参数:
θ t ← θ t − 1 + Δ θ t . \boldsymbol{\theta}_t \leftarrow \boldsymbol{\theta}_{t-1} +\boldsymbol{\Delta\theta}_t. θt←θt−1+Δθt.
3.7 NAdam 算法
一种自然的Adam算法的改进方法是引入Nesterov加速梯度,称为NAdam 算法。
4、梯度截断
参考资料:
https://blog.csdn.net/qq_41080850/article/details/85240479