在深度学习优化算法中,常用的梯度下降算法中一般会有一个参数 —— 动量(momentum)。此文章记录动量算法的原理,以及使用它的目的。
N.B. 此处的梯度下降算法是广义的,包括一般我们使用的是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. 关于梯度的几何意义,它具有幅值和方向。就像向量一下,我们举两个例子。虽然几个向量的幅值比较大,但如果他们的方向相差比较大,其平均值(例子用的是算术平均,但加权平均也同理)会相对衰减; 而当梯度方向相近时,其幅度不太会衰减。
他们的方向相差比较大,其平均值(例子用的是算术平均,但加权平均也同理)会相对衰减; 而当梯度方向相近时,其幅度不太会衰减。