码字不易,转载请注明出处~
tags: deep learning; optimizesr; Adadelta; RMSProp
AdaGrad虽然能够实现学习率的自适应,然而还是由于其本身存在的部分缺点导致使用起来并非很方便,比如学习率衰减比较快等。在凸优化问题中,是可以通过这种快速学习率衰减的方法来尽快达到最优点。然而,对于神经网络或者其它很多非凸问题,这种变化会导致网络在训练的中间就停止了参数的更新,从而达不到最优解,因此用起来问题还是存在的。而且,如果在网络刚开始训练的时候,梯度很大的话,那么在接下来的训练中会以非常小的学习率训练,想要改变这种情况,就得在开始的时候将学习率调整大一些。但是,如果在训练中还需要我们自己去调整学习率的话,那么这种“自适应”倒也没那么“自适应”。因此后面的Adadelta\RMSprop都在试图减轻这种衰减或者干脆改变策略,让它变得更加鲁棒。
局部梯度信息 vs 全局梯度信息
一种非常直观的做法就是,对于AdaGrad的学习率衰减不要那么大。原来不是从开始训练就一直在累计全部的梯度平方和么?那这会儿我们可以通过累计局部梯度信息,比如说本次之前的最近10次梯度平方和,那么这样的话,学习率衰减就会小很多。而最近的10次梯度累积信息到底怎么保存也是一个问题,因为对于神经网络来讲,参数数目动辄几百万,如果每一个参数的梯度信息都需要保存,尤其是参数值又比较大的情况,这样做需要的内存开销还是很大的。所以,Adadelta的作者采用了一种指数加权的移动平均的方法来进行计算。公式如下:
(1)E[g2]t=ρE[g2]t−1+(1−ρ)gt⨀gt\mathbb{E}[g^2]_t=\rho \mathbb{E}[g^2]_{t-1}+(1-\rho)g_t \bigodot g_t \tag{1}E[g2]t=ρE[g2]t−1+(1−ρ)gt⨀gt(1)
其中,ρ\rhoρ表示的是衰减因子,和Momentum法中的α\alphaα作用相似,主要用于控制在t时刻之前要累计多少之前的梯度信息或者我们有多大程度相信之前所累计的梯度信息;gtg_tgt是t时刻的梯度,通过下式计算:
(2)gt=1m∑i=1m∇θL(x(i),y(i),θt)g_t=\frac{1}{m}\sum_{i=1}^{m}\nabla_{\theta} L(x^{(i)}, y^{(i)},\theta_t)\tag{2}gt=m1i=1∑m∇θL(x(i),y(i),θt)(2)
为什么上面的公式有效呢?
如果将上面的式(1)进行进一步展开,我们可以得到下面的式子:
(3)E[g2]t=ρE[g2]t−1+(1−ρ)gt⨀gt=ρ[ρE[g2]t−2+(1−ρ)gt−1⨀gt−1]+(1−ρ)gt⨀gt=⋯=ρk[E[g2]t−k]+ρk−1(1−ρ)gt−k⨀t−k+⋯+(1−ρ)gt⨀gt
\begin{aligned}
\mathbb{E}[g^2]_t&=\rho \mathbb{E}[g^2]_{t-1}+(1-\rho)g_t \bigodot g_t \\
&=\rho[\rho\mathbb{E}[g^2]_{t-2}+(1-\rho)g_{t-1}\bigodot g_{t-1}]+(1-\rho)g_t \bigodot g_t \\
&=\cdots \\
&=\rho^k[\mathbb{E}[g^2]_{t-k}] + \rho^{k-1}(1-\rho)g_{t-k}\bigodot{t-k}+\cdots+(1-\rho)g_t \bigodot g_t
\end{aligned}\tag{3}
E[g2]t=ρE[g2]t−1+(1−ρ)gt⨀gt=ρ[ρE[g2]t−2+(1−ρ)gt−1⨀gt−1]+(1−ρ)gt⨀gt=⋯=ρk[E[g2]t−k]+ρk−1(1−ρ)gt−k⨀t−k+⋯+(1−ρ)gt⨀gt(3)
通常ρ\rhoρ都是小于1的正数,那么随着网络的不断迭代,初始时刻到现在的t时刻,每次累加的梯度信息所乘的因子是ρn、ρn−1⋯ρ\rho^n、\rho^{n-1} \cdots \rhoρn、ρn−1⋯ρ,这样的话,只要通过控制ρ\rhoρ的大小,就可以使每次累加的梯度信息的权重减小不同的程度,越接近当前时刻,梯度权重越大,离现在时刻越久远,其梯度权重越小,影响也就越小。因此,这种方法称为指数加权移动平均
当计算出了局部的梯度信息之后,我们可以模仿AdaGrad中的做法,使用其均方根(RootMeanSquareRoot Mean SquareRootMeanSquare)作为实际运算中的因子。表示为下面的公式:
(4)RMS[g]t=E[g2]t+εRMS[g]_t=\sqrt{\mathbb{E}[g^2]_t+\varepsilon}\tag{4} RMS[g]t=E[g2]t+ε(4)
其中的ε\varepsilonε同样是为了避免可能出现的除0错误,其值一般为10−610^{-6}10−6左右,因为上面的(3)式最终会出现在分母项中,如下:
(5)θt+1=θt−ηRMS[g]t⨀gt\theta_{t+1}=\theta_t-\frac{\eta}{RMS[g]_t}\bigodot g_t\tag{5}θt+1=θt−RMS[g]tη⨀gt(5)
其实,写到这里,我们的公式(4)就是RMSProp算法了。因为它采用了“局部的”权重信息,所以使得梯度累加不是那么大,而且也不会一直衰减,在实际使用中用的还是比较多的。但是,这个算法依然没能解决需要手动设定初始学习率η\etaη的问题。所以还需要别的方法。
改变分子的η\etaη
上面的RMSProp算法中,需要计算
(6)∇θt=−ηRMS[g]t⨀gt\nabla \theta_t=-\frac{\eta}{RMS[g]_t}\bigodot g_t\tag{6}∇θt=−RMS[g]tη⨀gt(6)
然后在这项基础上,进行权重的更新:
(7)θt+1=θt+∇θt\theta_{t+1}=\theta_t+\nabla \theta_t \tag{7}θt+1=θt+∇θt(7)
在上面我们已经知道了梯度的局部累积RMS[g],如果我们能够想办法将分子中的η\etaη换成一个能够根据梯度信息自动变化的量,那么就可以不用设置学习率了,从而也就实现了学习率的自适应。
因此,如果我们计算下面的公式:
(8)E[Δθ2]t=ρE[Δθ2]t−1+(1−ρ)Δθt⨀Δθt\mathbb{E}[\Delta \theta^2]_t=\rho \mathbb{E}[\Delta \theta^2]_{t-1}+(1-\rho)\Delta \theta_t \bigodot \Delta \theta_t\tag{8}E[Δθ2]t=ρE[Δθ2]t−1+(1−ρ)Δθt⨀Δθt(8)
同样,对其进行开方处理,则可以的得到RMS[Δθ]tRMS[\Delta \theta]_tRMS[Δθ]t。
目前,我们仍然不知道Δθt\Delta \theta_tΔθt,因为这项其实正事我们要求的。但是,假设我们所需要学习的函数映射在局部是光滑的,那么可以用前一次更新的参数Δθt−1\Delta \theta_{t-1}Δθt−1近似Δθt\Delta \theta_tΔθt
这样的话,参数的更新就变成了
(9)θt+1=θt−RMS[Δθ]t−1RMS[g]t⨀gt\theta_{t+1}=\theta_t-\frac{RMS[\Delta \theta]_{t-1}}{RMS[g]_t}\bigodot g_t\tag{9}θt+1=θt−RMS[g]tRMS[Δθ]t−1⨀gt(9)
这样,就完全摆脱了学习率,可以根据历史参数更新和当前计算的梯度来更新权重参数。
其实,这块的推导过程比较复杂,至少对于我这种数学基础较差的是比较吃力的,真正背后的原理还是得靠不断积累理解,而我这里仅仅先知道这样一个结果吧。
RMSprop和Adadelta
通过上面的式子对比,其实可以看到,如果在RMSprop中将ρ\rhoρ设为0.5,那么指数加权平均过程就变成了梯度平方和的平均数。而RMSprop其实是Adadelta的一种特殊情况,其依然靠的是全局的学习率。
参考
- M. D. Zeiler, “Adadelta: An Adaptive Learning Rate Method” (2012)
- G. Hinton, N. Srivastava, K. Swersky, “Lecture 6a: Overview of mini–batch gradient descent” (2012)
- I. Goodfellow, Y. Bengio, A. Courville, “Deep Learning” (2016)