pytorch学习系列(4):常用优化算法

1 优化算法的挑战

1.1 局部最小值

1.2 鞍点

损失函数容易陷入这两个点,而下一步的梯度很小或者为0,不能继续训练。
不过,对于神经网络这样非常复杂的高维非凸模型,已经有理论证明局部最小值与全局最小值非常接近,所以第一个问题目前不算太关注,鞍点才是更关注的问题。

2 梯度下降算法

w:参数;f(w):损失函数; η \eta η:学习率;t:迭代次数(iteration); ▽ \bigtriangledown :梯度

2.1 全量梯度下降(BGD,batch gradient descent)

Δ w t = − ▽ f ( w t ) \Delta w_{t}=-\bigtriangledown f(w_{t}) Δwt=f(wt)

w t + 1 = w t + η ∗ Δ w t w_{t+1}=w_{t}+\eta*\Delta w_{t} wt+1=wt+ηΔwt
这里的损失函数计算的是所有训练集数据的损失。

优点:
一般来说收敛性能比较好

缺点:
1.训练速度慢
2.对内存和算力的要求比较高,只适合小数据集的学习,目前几乎不会使用这种方法。

2.2 随机梯度下降

计算公式与全量梯度下降相同,只不过这里一次只取一个样本而不是所有的样本。

优点:
训练速度快

缺点:
每次只有一个样本,随机性比较大,很可能不收敛,非常震荡,目前几乎不会使用这种方法

2.3 小批量随机梯度下降(mini-batch stochastc gradient descent,SGD)

注:其实SGD应该是上面那个单样本随机梯度下降的简称,但现在它已经不用了,所以默认小批量随机梯度下降为SGD

每次随机取相同数量的样本,这个样本数量为batch size.

优点:
结合了全量和单样本梯度下降的优点,很大程度上减弱了二者的劣势。

缺点(与下面的几种算法相比):
1.收敛比较慢;
2.容易陷入鞍点,尤其是在这些点会非常震荡,如果可视化出来,会呈现“之”字型来回曲折;
3.对学习率比较敏感,需要合适的学习率。

2.4 带有动量的随机梯度下降(SGD with momentum)

针对SGD容易陷入鞍点的问题,这里借助物理学的动量的概念(不如说是惯性更好理解)。当损失到达一个梯度很小的地方时,SGD可能就难以继续下去了,但是类比于小球在坑坑洼洼的空间滚动,当其落入局部洼地(局部最小值)或平缓地带(鞍点),借助于惯性还是可以继续走下去的,这个惯性是当前的速度决定的,于是在这里引入速度变量 v t v_{t} vt,且 v 0 = 0 v_{0}=0 v0=0.
Δ w t = − ▽ f ( w t ) \Delta w_{t}=-\bigtriangledown f(w_{t}) Δwt=f(wt)

v t + 1 = γ ∗ v t + η ∗ Δ w t v_{t+1}=\gamma *v_{t}+\eta*\Delta w_{t} vt+1=γvt+ηΔwt

w t + 1 = w t + v t + 1 w_{t+1}=w_{t}+v_{t+1} wt+1=wt+vt+1

其中 γ \gamma γ为常量(一般为0.9),代表衰减(物理里的摩擦)系数。

优点:
1.加速收敛,减小震荡;
2.缓解SGD陷入鞍点的问题。

缺点(与后面的几种算法相比):
依然有震荡现象

2.5 NAG(Nesterov accelerated gradient)

在SGD with m 的算法中,用当前时刻的梯度来计算下一时刻的速度,这可能不是非常准确,NAG方法先估计下一时刻的梯度,再用这个梯度来求速度。
Δ w t = − ▽ f ( w t + γ ∗ v t ) \Delta w_{t}=-\bigtriangledown f(w_{t}+\gamma*v_{t}) Δwt=f(wt+γvt)

v t + 1 = γ ∗ v t + η ∗ Δ w t v_{t+1}=\gamma *v_{t}+\eta*\Delta w_{t} vt+1=γvt+ηΔwt

w t + 1 = w t + v t + 1 w_{t+1}=w_{t}+v_{t+1} wt+1=wt+vt+1
该方法没有对参数求梯度,这就没有计算损失函数,所以在实际中不好用,一般会对 w t + γ ∗ v t w_{t}+\gamma*v_{t} wt+γvt进行换元,使得能够同时计算对参数的梯度。
优点:
震荡情况比SGD with m更小

总结以上五种优化算法,其特点是对所有的参数使用相同的学习率 η \eta η。但实际上,神经网络参数非常多,在训练过程中有的参数会更新得很快,下降很快;有的参数更新得很慢,下降很慢。如果对不同的更新快的参数用小的学习率,对更新慢的参数用大的学习率,能够使得所有的参数都更新的比较好。于是出现了下面的自适应优化算法。

pytorch用一个优化器提供了SGD、SGD with m和NAG的算法的实现,由于全量和单样本梯度下降几乎不会用到,所以pytorch并不提供相关算法,而且这两种也可以通过改变batch_size的大小来实现。

optimizer = optim.SGD(params, lr=required, momentum=0, dampening=0, weight_decay=0, nesterov=False)

lr:学习率
momentum:动量大小,即 γ \gamma γ,一般设为0.9,如果为0则不带动量项。
weight_decay:l2正则化的系数
nesterov:是否使用NAG优化算法

3 自适应优化算法

3.1 Adagrad

该方法引入了各个维度的参数的梯度的平方和 ∑ i = 1 t ( ▽ f ( w i ) ) 2 \sum_{i=1}^{t}(\bigtriangledown f(w_{i}))^{2} i=1t(f(wi))2,其中i为参数的维度, ε \varepsilon ε为很小的正数(一般为1e-7),防止分母为0.
( w t + 1 ) i = ( w t ) i − η ∑ i = 1 t ( ▽ f ( w i ) ) 2 + ε ∗ ( ▽ f ( w i ) ) i (w_{t+1})_{i}=(w_{t})_{i}-\frac{\eta}{\sqrt{\sum_{i=1}^{t}(\bigtriangledown f(w_{i}))^{2}+\varepsilon}}*(\bigtriangledown f(w_{i}))_{i} (wt+1)i=(wt)ii=1t(f(wi))2+ε η(f(wi))i

学习率实际上是 η ∑ i = 1 t ( ▽ f ( w i ) ) 2 \frac{\eta}{\sum_{i=1}^{t}(\bigtriangledown f(w_{i}))^{2}} i=1t(f(wi))2η,当这个维度的参数的历史梯度较大时,学习率较小,当其历史梯度较小时,学习率较大,这就实现了对不同的参数自适应分配学习率。

优点:
1.实现了不同参数的学习率自适应分配;
2.比较适合具有稀疏梯度的模型,这种模型的特点就是不同参数梯度差距比较大

缺点:
在训练的后期,梯度平方和的累积项可能会非常大,导致学习率很低,使得无法继续更新,早早就不能训练 (尤其是在非凸的神经网络模型上,而在凸函数模型上无此问题)

optimizer = optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)

指数加权移动平均(EWMA)

RMSProp算法用到了指数加权移动平均。
这是一种预测方法,对历史最近的一部分观察值赋予不同权重,并且靠近当前的值赋予大权重,远离当前的值赋予小权重,求得移动平均值,以该移动平均值来预测未来的值。
y t y_{t} yt为要预测的变量, x t x_{t} xt为相关的一个变量.
y t = γ ∗ y t − 1 + ( 1 − γ ) ∗ x t = ( 1 − γ ) ∗ x t + γ ∗ y t − 1 = ( 1 − γ ) ∗ x t + ( 1 − γ ) ∗ γ ∗ ∗ x t − 1 + γ 2 ∗ y t − 2 . . . . . . . y_{t}=\gamma*y_{t-1}+(1-\gamma)*x_{t} =(1-\gamma)*x_{t}+\gamma*y_{t-1}=(1-\gamma)*x_{t}+(1-\gamma)*\gamma**x_{t-1}+\gamma^{2}*y_{t-2}....... yt=γyt1+(1γ)xt=(1γ)xt+γyt1=(1γ)xt+(1γ)γxt1+γ2yt2.......
换元 n = 1 1 − γ n=\frac{1}{1-\gamma} n=1γ1,则 ( 1 − 1 n ) n = γ 1 1 − γ (1-\frac{1}{n})^{n}=\gamma^{\frac{1}{1-\gamma}} (1n1)n=γ1γ1
lim ⁡ n → + ∞ ( 1 − 1 n ) n = e − 1 < 1 \lim\limits_{n\to+\infty}(1-\frac{1}{n})^{n}=e_{-1}<1 n+lim(1n1)n=e1<1
所以当 γ \gamma γ接近于1时, γ 1 1 − γ = e − 1 \gamma^{\frac{1}{1-\gamma}}=e^{-1} γ1γ1=e1,于是可以忽略没有 γ 1 1 − γ \gamma^{\frac{1}{1-\gamma}} γ1γ1低的项。
因此 y t = ( 1 − γ ) ∗ ∑ i = 0 1 1 − γ − 1 v i ∗ x t − i y_{t}=(1-\gamma)*\sum_{i=0}^{\frac{1}{1-\gamma}-1}v^{i}*x_{t-i} yt=(1γ)i=01γ11vixti
y t y_{t} yt就是最近的 1 1 − γ \frac{1}{1-\gamma} 1γ1时间步的 x t x_{t} xt的加权平均。

3.2 RMSProp

与Adagrad相比,不再累积历史全部梯度的平方和,而是只取最近的过去的一段时间内的梯度信息
v t + 1 = γ ∗ v t + ( 1 − γ ) ∗ ( ▽ f ( w t + 1 ) ) 2 v_{t+1}=\gamma *v_{t}+(1-\gamma)*(\bigtriangledown f(w_{t+1}))^{2} vt+1=γvt+(1γ)(f(wt+1))2

( w t + 1 ) i = ( w t ) i − η v t + 1 + ε ∗ ( ▽ f ( w i ) ) i (w_{t+1})_{i}=(w_{t})_{i}-\frac{\eta}{\sqrt{v_{t+1}+\varepsilon}}*(\bigtriangledown f(w_{i}))_{i} (wt+1)i=(wt)ivt+1+ε η(f(wi))i
v t + 1 v_{t+1} vt+1 ( ▽ f ( w t + 1 ) ) 2 (\bigtriangledown f(w_{t+1}))^{2} (f(wt+1))2的指数加权移动平均,即 1 1 − γ \frac{1}{1-\gamma} 1γ1个时间步长的梯度平方和的加权平均,越靠近当前时间的梯度的权重越大。

优点:
解决了Adagrad在训练后半期难以更新的问题

optimizer =optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)

3.3 AdaDelta

对RMSProp做了改进,引入了一个额外的变量 Δ x t \Delta x_{t} Δxt,且 x 0 = 0 x_{0}=0 x0=0,用 Δ x t \sqrt{\Delta x_{t}} Δxt 代替学习率
v t + 1 = γ ∗ v t + ( 1 − γ ) ∗ ( ▽ f ( w t + 1 ) ) 2 v_{t+1}=\gamma*v_{t}+(1-\gamma)*(\bigtriangledown f(w_{t+1}))^{2} vt+1=γvt+(1γ)(f(wt+1))2

( w t + 1 ) i = ( w t ) i − Δ x t + ε v t + 1 + ε ∗ ( ▽ f ( w t ) ) i (w_{t+1})_{i}=(w_{t})_{i}-\sqrt{\frac{\Delta x_{t}+\varepsilon}{v_{t+1}+\varepsilon}}*(\bigtriangledown f(w_{t}))_{i} (wt+1)i=(wt)ivt+1+εΔxt+ε (f(wt))i

Δ x t + 1 = γ ∗ Δ x t + ( 1 − γ ) ∗ ( Δ x t + ε v t + 1 + ε ∗ ▽ f ( w t ) i ) 2 \Delta x_{t+1}=\gamma *\Delta x_{t}+(1-\gamma)*({\sqrt{\frac{\Delta x_{t}+\varepsilon}{v_{t+1}+\varepsilon}}*\bigtriangledown f(w_{t})_{i}})^2 Δxt+1=γΔxt+(1γ)(vt+1+εΔxt+ε f(wt)i)2

Δ x t + 1 \Delta x_{t+1} Δxt+1 ( Δ x t + ε v t + 1 + ε ∗ ▽ f ( w t ) i ) 2 ({\sqrt{\frac{\Delta x_{t}+\varepsilon}{v_{t+1}+\varepsilon}}*\bigtriangledown f(w_{t})_{i}})^2 (vt+1+εΔxt+ε f(wt)i)2的指数加权移动平均。

优点:
1.不需要设定全局学习率,一下子解决了调参过程中最重要的参数的选择
2.同样解决了Adagrad在训练后半期难以更新的问题

optimizer = optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)

3.4 Adam

Adam相当于RMSProp+momentum,将两类方法的优势结合起来,集大成者。momentum使用了一阶梯度,RMSProp使用了二阶梯度,Adam二者均使用。
一 阶 梯 度 : m t = β 1 ∗ m t − 1 + ( 1 − β 1 ) ∗ ▽ f ( w t ) 一阶梯度:m_{t}=\beta_{1}*m_{t-1}+(1-\beta_{1})*\bigtriangledown f(w_{t}) mt=β1mt1+(1β1)f(wt)

二 阶 梯 度 : v t = β 2 ∗ v t − 1 + ( 1 − β 2 ) ∗ ( ▽ f ( w t ) ) 2 二阶梯度:v_{t}=\beta_{2}*v_{t-1}+(1-\beta_{2})*(\bigtriangledown f(w_{t}))^{2} vt=β2vt1+(1β2)(f(wt))2

偏差修正:在训练的前期,梯度权值之和比较小,需要将权值之和修正为1.
m t ^ = m t 1 − β 1 \hat{m_{t}}=\frac{m_{t}}{1-\beta_{1}} mt^=1β1mt

v t ^ = v t 1 − β 2 \hat{v_{t}}=\frac{v_{t}}{1-\beta_{2}} vt^=1β2vt

( w t + 1 ) i = ( w t ) i − η v t ^ + ε ∗ m t ^ (w_{t+1})_{i}=(w_{t})_{i}-\frac{\eta}{\sqrt{\hat{v_{t}}}+\varepsilon}*\hat{m_{t}} (wt+1)i=(wt)ivt^ +εηmt^
其中 β 1 = 0.9 \beta_{1}=0.9 β1=0.9, β 2 = 0.999 \beta_{2}=0.999 β2=0.999

optimizer =optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)

4 总结

pytorch还提供了另外四种优化算法,由于用的不是很多,我也没有仔细研究。
以目前的情况来看,Adam成为了一个无脑选择,绝大数工程和研究都用Adam,但实际上有研究证明自适应的算法不一定能找到最优的结果,这个只能算是“懒人做法”。使用最原始的SGD再配合更合适的学习率下降和训练技巧能获得更好的结果,但这对算法和模型的理解要求比较高,毕竟深度学习的研究中优化算法往往不是考虑的最重要因素,更重要的是结构模型、数据等,所以使得Adam成为了万金油的选择。

  • 12
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值