理解梯度下降算法中的动量
在深度学习优化算法中,常用的梯度下降算法中一般会有一个参数 —— 动量(momentum)。此文章记录动量算法的原理,以及使用它的目的。
N.B. 此处的梯度下降算法是广义的,包括一般我们使用的是mini-batch SGD。
梯度下降:GD, SGD, mini-batch SGD
在理解动量之前,我们有必要先了解梯度下降算法随机梯度下降算法。我们先假设,优化的目标函数为:
f
(
x
⃗
)
:
ℜ
d
→
ℜ
w
h
e
r
e
,
x
⃗
=
[
x
1
,
x
2
,
.
.
.
,
x
d
]
T
\begin{matrix} f(\vec x) : \real^d \rightarrow \real\\ where, \vec x = [x_1, x_2, ..., x_d]^T \end{matrix}
f(x):ℜd→ℜwhere,x=[x1,x2,...,xd]T
则其梯度向量表达式为:
∇
p
f
(
x
⃗
)
=
[
∂
f
(
x
⃗
)
∂
x
1
,
∂
f
(
x
⃗
)
∂
x
2
,
.
.
.
,
∂
f
(
x
⃗
)
∂
x
d
]
T
\nabla _pf(\vec x) = [\frac{\partial f(\vec x)}{\partial x_1}, \frac{\partial f(\vec x)}{\partial x_2}, ..., \frac{\partial f(\vec x)}{\partial x_d}]^T
∇pf(x)=[∂x1∂f(x),∂x2∂f(x),...,∂xd∂f(x)]T
GD算法更新参数的方式就是,将自变量x在梯度方向上改变一定的幅度(由学习率决定),即:
x
⃗
←
x
⃗
−
η
∇
f
(
x
⃗
)
\vec x \gets \vec x - \eta \nabla f(\vec x)
x←x−η∇f(x)
上式中,eta即为学习率,取整数,并且一般是一个比较小的数。至于为什么GD算法能让函数值在迭代过程中减小,并在理想情况下回趋于稳定,此处不进行论述。通过高数课上学习的知识,我们知道,针对多元函数(向量函数),其在某点p上(改点的各个维度偏导数均存在的情况下)的梯度方向,为点方向导数最大的方向。所以,GD算法能够使变量在目标函数值下降最快的方向更新,又称为最陡下降(steepest descent)。
N.B. 需要注意一点,在优化过程中,对于目标函数f来说,自变量 x 是我们的模型参数,而不是训练样本输入。这个x是个广义上的向量(或称张量)。
深度学习中,我们的训练集往往有大量样本。假设训练集样本量为 n,深度学习中一般将 n 个样本的平均损失值作为样本损失,所以目标函数可表示为:
f
(
x
⃗
)
=
1
n
∑
i
=
1
n
f
i
(
x
⃗
)
f(\vec x) = \frac 1n\sum_{i=1}^{n}f_i(\vec x)
f(x)=n1i=1∑nfi(x)
梯度表达式为:
∇
f
(
x
⃗
)
=
1
n
∑
i
=
1
n
∇
f
i
(
x
⃗
)
\nabla f(\vec x) = \frac 1n\sum_{i=1}^{n}\nabla f_i(\vec x)
∇f(x)=n1i=1∑n∇fi(x)
梯度的shape还是 d 维度的向量,更新参数时仍然是采用上一节的迭代公式。所以,我们会发现,每迭代一次(后面,我们称为step)保存n个样本输入时,分别求得的模型参数的梯度,然后求平均才能进行迭代。所以,每次模型参数迭代的计算开销为O(n),计算复杂度随着n线性增长。而采用SGD算法可以减少每次迭代(每个step)的计算开销。
我们还是先给出公式。SGD算法就是在数据集的n个样本中采用随机均匀采样一个样本索引 i ,并且计算 i 此时的梯度来完成一次迭代:
x
⃗
←
x
⃗
−
η
∇
f
i
(
x
⃗
)
\vec x \gets \vec x - \eta \nabla f_i(\vec x)
x←x−η∇fi(x)
这样,就可以减少每次更新模型参数的开销,此时每迭代一次的开销是O(1)。并且,从概率上来讲,随机梯度是对梯度的无偏估计,是一个良好的替代。
N.B. 降低每个此更新模型参数的开销,虽然会降低需要申请的内存,并不是说能够大大减少训练的时间。 两者更新一次模型参数所达到的效果是不一样的—— 这是因为,虽然理论上随机采样一个样本的梯度可以作为平均梯度的无偏估计,但因为训练样本的差异性等原因,实际上SGD更新一次参数的效果不如GD。
一般来说,如果采用GD算法进行优化,一个epoch是一次迭代,每个epoch只会更新一次全局梯度和模型参数;采用SGD算法,一个epoch的会迭代 n 次,模型参数也会更新n次。后面我们要说的mini-batch SGD也是类似的道理,假设批大小为B,则一般一个epoch会包括 n // B 次迭代。
接下来,我们来了解mini-batch SGD。在SGD的基础上,我们还可以一次采样一个小批量的样本,然后利用该小批量来计算梯度。这样做比每次仅采样一个样本,能够是的计算的梯度值更加符合期望的梯度值,排除减少异常样本的干扰。假设批大小(batch size)大小为 B ,时间 t 采样的一个batch样本为 Psi_t,则梯度表达式为:
∇
f
Ψ
t
(
x
⃗
t
)
=
1
B
∑
i
∈
Ψ
t
∇
f
i
(
x
⃗
t
−
1
)
\nabla f_{\Psi_t}(\vec x_t)= \frac{1}{B}\sum_{i \in \Psi_t}{\nabla f_i(\vec x_{t-1})}
∇fΨt(xt)=B1i∈Ψt∑∇fi(xt−1)
参数更新方式为:
x
⃗
t
←
x
⃗
t
−
1
−
η
t
∇
f
Ψ
t
(
x
⃗
t
)
\vec x_t \gets \vec x_{t-1} -\eta_t\nabla f_{\Psi_t}(\vec x_t)
xt←xt−1−ηt∇fΨt(xt)
和前述不同的是,这里学习率也带上了时间脚标t,这说明在使用mini-batch SGD算法时,一般会每过一定迭代之后对学习率进行衰减。采用mini-batch SGD的开销是O(B),当batch size = 1时,该方法就是SGD。在经验上,一般选取的batch size越大, 相应地一般要提升训练epoch的数量。
指数加权移动平均 -> 动量
指数加权移动平均算法(Exponentially Weighted Moving-Average, EWMA),是通过历史值和当前时间的观测值来估计一个时间序列的方法。给定一个超参数γ属于区间[0, 1],算法表示如下:
对
于
时
间
序
列
,
x
=
[
x
0
,
x
1
,
.
.
.
,
x
t
]
有
,
估
计
序
列
,
x
^
=
[
x
^
0
,
x
^
1
,
.
.
.
,
x
^
t
]
其
中
,
x
^
t
=
γ
x
^
t
−
1
+
(
1
−
γ
)
x
t
对于时间序列, \bold x = [x_0, x_1, ..., x_t] \\ 有,估计序列, \hat{\bold x} = [\hat x_0, \hat x_1, ..., \hat x_t] \\ 其中, \hat x_t = \gamma \hat x_{t-1} + (1-\gamma)x_t
对于时间序列,x=[x0,x1,...,xt]有,估计序列,x^=[x^0,x^1,...,x^t]其中,x^t=γx^t−1+(1−γ)xt
也就是说,时刻 t 的估计值由t-1时刻的估计值和时刻t的观测值加权平均得到。我们来更直观地看一下EWMA算法的作用,将时刻 t 估计值的转移方程展开:
x
^
t
=
(
1
−
γ
)
x
t
+
γ
x
^
t
−
1
=
(
1
−
γ
)
x
t
+
(
1
−
γ
)
γ
x
t
−
1
+
γ
2
x
^
t
−
2
.
.
.
≈
(
1
−
γ
)
x
t
+
(
1
−
γ
)
γ
x
t
−
1
+
(
1
−
γ
)
γ
2
x
t
−
2
+
.
.
.
+
(
1
−
γ
)
γ
n
x
t
−
n
+
o
[
(
1
−
γ
)
γ
n
x
t
−
n
]
\hat x_t = (1-\gamma)x_t + \gamma \hat x_{t-1} \\ = (1-\gamma)x_t+(1-\gamma)\gamma x_{t-1} + \gamma^2\hat x_{t-2}\\ ... \\ \approx (1-\gamma)x_t+(1-\gamma)\gamma x_{t-1} + (1-\gamma)\gamma^2 x_{t-2} + ... + (1-\gamma)\gamma^nx_{t-n} + o[(1-\gamma)\gamma^nx_{t-n}]
x^t=(1−γ)xt+γx^t−1=(1−γ)xt+(1−γ)γxt−1+γ2x^t−2...≈(1−γ)xt+(1−γ)γxt−1+(1−γ)γ2xt−2+...+(1−γ)γnxt−n+o[(1−γ)γnxt−n]
上式中,最后一个等式右边最后一项表示比倒数第二项更高阶的项。此处,我们令 n = 1/(1-γ),并且假设 γ 趋近于1,分析上述展开式倒数第二项的系数:
n
=
1
/
(
1
−
γ
)
⟹
(
1
−
γ
)
γ
n
=
(
1
−
1
n
)
n
n
令
γ
→
1
⟹
n
→
∞
于
是
,
(
1
−
γ
)
γ
n
≈
lim
n
→
∞
(
1
−
1
n
)
n
n
∵
lim
n
→
∞
(
1
−
1
n
)
n
=
e
lim
x
→
0
l
n
(
1
−
x
)
x
=
e
lim
x
→
0
1
x
−
1
=
1
e
⟹
当
γ
→
1
时
,
(
1
−
γ
)
γ
n
≈
0
n = 1 /(1-\gamma) \implies (1-\gamma)\gamma ^n = \frac{(1-\frac{1}{n})^n}{n} \\ 令 \gamma \to 1 \implies n\to \infin \\ 于是,(1-\gamma)\gamma ^n \approx \lim_{n\to\infin}{\frac{(1-\frac{1}{n})^n}{n}} \\ \because \lim_{n\to\infin}{(1-\frac{1}{n})^n} = e^{\lim_{x\to0}{\frac{ln(1-x)}{x}}}=e^{\lim_{x\to0}{\frac{1}{x-1}}}=\frac1e \\ \implies 当\gamma \to 1时, (1-\gamma)\gamma^n \approx 0
n=1/(1−γ)⟹(1−γ)γn=n(1−n1)n令γ→1⟹n→∞于是,(1−γ)γn≈n→∞limn(1−n1)n∵n→∞lim(1−n1)n=elimx→0xln(1−x)=elimx→0x−11=e1⟹当γ→1时,(1−γ)γn≈0
求该极限,我们可以得出该系数在上述条件下趋近于0,所以我们忽略倒数第二项和后面的高阶项,有:
x
^
t
=
(
1
−
γ
)
x
t
+
γ
x
^
t
−
1
≈
(
1
−
γ
)
x
t
+
(
1
−
γ
)
γ
x
t
−
1
+
(
1
−
γ
)
γ
2
x
t
−
2
+
.
.
.
+
(
1
−
γ
)
γ
n
−
1
x
t
−
n
+
1
\hat x_t = (1-\gamma)x_t + \gamma \hat x_{t-1} \\ \approx (1-\gamma)x_t+(1-\gamma)\gamma x_{t-1} + (1-\gamma)\gamma^2 x_{t-2} + ... + (1-\gamma)\gamma^{n-1}x_{t-n+1}
x^t=(1−γ)xt+γx^t−1≈(1−γ)xt+(1−γ)γxt−1+(1−γ)γ2xt−2+...+(1−γ)γn−1xt−n+1
所以,在实际使用时,我们可以将EWMA的在时刻t的估计值看成是对最近n= 1 / (1-γ)个时间步的观测值的加权平均,并且时间距当前时刻越近的权重越高,时间越远的权重越低;γ=0时只使用当前时刻的观测值更新估计序列,γ 越接近 1 其使用的过去时刻越多。 比如,当我们设置 γ=0.9时,可以看成使用最近 n = 1/(1-0.9) = 10步观测值的加权平均;当我们设置γ=0.96时,可以看成使用最近25步观测值的加权平均。
接下来,给出动量法的迭代公式。以广义的SGD算法为基础,动量法引入一个超参γ,用于调节梯度下降的过程:
v
t
←
γ
v
t
−
1
+
η
t
∇
f
t
;
w
h
e
r
e
,
γ
∈
[
0
,
1
]
x
⃗
t
←
x
⃗
t
−
1
−
v
t
v_t \gets \gamma v_{t-1} + \eta_t\nabla f_t ; where, \gamma \in[0, 1] \\ \vec x_t \gets \vec x_{t-1} - v_t
vt←γvt−1+ηt∇ft;where,γ∈[0,1]xt←xt−1−vt
上式中γ就是引入的动量超参,当 γ=0 时,等价于SGD算法。假设 γ!=1, 我们对上式的一个式子进行变形,使其编程EWMA算法的表观形式:
v
t
←
γ
v
t
−
1
+
(
1
−
γ
)
η
t
∇
f
t
1
−
γ
v_t \gets \gamma v_{t-1} + (1-\gamma)\frac{\eta_t\nabla f_t}{1-\gamma}
vt←γvt−1+(1−γ)1−γηt∇ft
按照上面对EWMA的解释,可以看出,这个速度变量v_t实际上可以认为是对时间序列
η
t
∇
f
t
1
−
γ
\frac{\eta_t\nabla f_t}{1-\gamma}
1−γηt∇ft
的最近n= 1/(1-γ) 项的指数加权移动平均,时间越近的权重越高。同样,当γ=0.95时,我们可以认为这个加权平均使用的该时间序列最近20项的梯度、学习率的观测值。这样做的一个直观表现就是,如果目标函数最近 n 个时间步的梯度方向比较一致,那么 t 时刻的梯度加上t-1时刻的速度会让 t 时刻的速度变量较大,则模型参数的改变量就大;若这几个时间步内梯度方向变化较大,会造成其加权平均值较小,则模型参数的改变量就相对小。
N.B. 关于梯度的几何意义,它具有幅值和方向。就像向量一下,我们举两个例子。虽然几个向量的幅值比较大,但如果他们的方向相差比较大,其平均值(例子用的是算术平均,但加权平均也同理)会相对衰减; 而当梯度方向相近时,其幅度不太会衰减。
他们的方向相差比较大,其平均值(例子用的是算术平均,但加权平均也同理)会相对衰减; 而当梯度方向相近时,其幅度不太会衰减。