深度学习中的优化算法介绍

文章目录

BGD/MBGD/SGD

梯度下降的公式为:
θi+1=θiηθiL(θi) \theta_{i+1}=\theta_{i}-\eta \frac{\partial}{\partial \theta_{i}} L(\theta_{i}) θi+1​=θi​−η∂θi​∂​L(θi​)
对某个参数w的梯度下降公式就是上一步的该参数w的值减去学习率乘以损失函数对w的梯度值。损失函数对w的偏导数值就是梯度。需要注意的是梯度下降总是减去梯度。
BGD/MBGD/SGD的区别主要在于损失函数的计算:
J(θ)=12mi=1m(hθ(x(i))y(i))2 J(\theta)=\frac{1}{2 m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2} J(θ)=2m1​i=1∑m​(hθ​(x(i))−y(i))2
BGD中,用于计算损失函数的是全体样本epoch;MBGD中,用于计算损失函数的是一个小批量样本batch_size;SGD中,用于计算损失函数的是单个样本。

Momentum

vt=γvt1+ηθJ(θ) v_{t}=\gamma v_{t-1}+\eta \nabla_{\theta} J(\theta) vt​=γvt−1​+η∇θ​J(θ)
θ=θvt \theta=\theta-v_{t} θ=θ−vt​
θ为权重参数,衰减值γ通常设定为0.9,或相近的某个值。
可以看到参数更新时不是直接减去学习率乘以上一步梯度,而是减去动量vt。vt由上一步的动量vt-1乘以衰减值γ,再加上上一步的学习率乘以梯度。
这样做的好处是,如果当前步的梯度与上一步梯度方向相同,那么这种计算会增大动量vt;如果当前步的梯度与上一步梯度方向相反,则会减小动量vt。
这样如果我们再局部最优点附件震荡收敛时,当前步的梯度与震荡的前一步的梯度方向相反。因此原本在局部最优点要大幅震荡徘徊的梯度,主要受到前一时刻的影响,而导致在当前时刻的梯度幅度减小。 这使得Momentum算法收敛速度比普通的梯度下降法更快。

NAG

vt=γvt1+ηθJ(θγvt1) v_{t}=\gamma v_{t-1}+\eta \nabla_{\theta} J\left(\theta-\gamma v_{t-1}\right) vt​=γvt−1​+η∇θ​J(θ−γvt−1​)
θ=θvt \theta=\theta-v_{t} θ=θ−vt​
θ为权重参数,衰减值γ通常设定为0.9。
NAG算法全称是Nesterov accelerated gradient,是对Momentum的改进。计算vt时求梯度时,损失函数中的参数θ会减去上一步的动量vt-1与衰减值γ的乘积,然后再对这个损失函数求梯度。
这使得我们能预测参数θ下一位置的近似值。这样我们就可以通过计算参数未来位置的近似值上的梯度"预见未来"。
NAG可以使RNN神经网络在很多任务上有更好的表现。

Adagrad

ηt=ηt1+gt2 \eta_{t}=\eta_{t-1}+g_{t}^{2} ηt​=ηt−1​+gt2​
θt+1=θtηnt+ϵgt \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{n_{t}+\epsilon}} * g_{t} θt+1​=θt​−nt​+ϵ​η​∗gt​
θ为权重参数。t代表每一次迭代。g代表第t次迭代时对θ得梯度。ϵ为平滑因子,避免除数为零。
可以看到学习率是初始学习率η除以过去每次迭代的梯度的平方之和。所以学习率会逐渐变小。对于变化不剧烈的参数,它们的梯度一直比较小,因此学习率就可以保持在比较大的水平;而对于变化剧烈的参数,它们的梯度值比较大,学习率相对就小一些。
基于上面这个特性,Adagrad方法对稀疏参数进行大幅更新和对频繁参数进行小幅更新。因此,Adagrad方法非常适合处理稀疏数据。

AdaDelta/RMSProp

论文:ADADELTA: an adaptive learning rate method
论文地址:https://arxiv.org/pdf/1212.5701v1.pdf
E(gt2)=E(gt12)+(1γ)gt2 E(g_{t}^{2})=E(g_{t-1}^{2})+(1-\gamma) g_{t}^{2} E(gt2​)=E(gt−12​)+(1−γ)gt2​
θt=ηE(gt2)+ϵgt \triangle \theta_{t}=-\frac{\eta}{\sqrt{E(g_{t}^{2})+\epsilon}} \cdot g_{t} △θt​=−E(gt2​)+ϵ​η​⋅gt​
θt=ηRMS(gt)gt \triangle \theta_{t}=-\frac{\eta}{RMS(g_{t})} g_{t} △θt​=−RMS(gt​)η​gt​
θt=RMS(θt1)RMS(gt)gt \triangle \theta_{t}=-\frac{RMS(\triangle \theta_{t-1})}{RMS(g_{t})} g_{t} △θt​=−RMS(gt​)RMS(△θt−1​)​gt​
θt+1=θt+θt \theta_{t+1}=\theta_{t}+\triangle \theta_{t} θt+1​=θt​+△θt​
衰减值γ通常设定为0.9。
AdaDelta是对Adagrad方法的改进。AdaDelta的梯度和递归地定义成历史梯度平方的衰减平均值。动态平均值E仅仅取决于当前的梯度值与上一时刻的平均值。将分母简记为RMS,表示梯度的均方根误差。此外,还将学习率η换成了 RMS[Δθ],这样我们不需要设置基础学习率η。
从多个数据集情况来看,AdaDelta在训练初期和中期,具有非常不错的加速效果。但是到训练后期,进入局部最小值雷区之后,AdaDelta就会反复在局部最小值附近抖动。主要体现在验证集错误率上,脱离不了局部最小值吸引盆。这时,切换成动量SGD,如果把学习率降低一个量级,就会发现验证集正确率有2%~5%的提升。
个人猜测使用SGD时,因为人工学习率的量级降低,给训练造成一个巨大的抖动,从一个局部最小值,抖动到了另一个局部最小值,而AdaDelta的二阶近似计算,或者说所有二阶方法,则不会产生这么大的抖动,所以很难从某个局部最小值中抖出来。
RMSProp和AdaDelta基本一样。

Adam

论文:ADAM: A METHOD FOR STOCHASTIC OPTIMIZATION
论文地址:https://arxiv.org/pdf/1412.6980.pdf
gt=θJ(θt1) g_{t}=\nabla_{\theta} J\left(\theta_{\mathrm{t}-1}\right) gt​=∇θ​J(θt−1​)
mt=β1mt1+(1β1)gt m_{t}=\beta_{1} m_{t-1}+\left(1-\beta_{1}\right) g_{t} mt​=β1​mt−1​+(1−β1​)gt​
vt=β2vt1+(1β2)gt2 v_{t}=\beta_{2} v_{t-1}+\left(1-\beta_{2}\right) g_{t}^{2} vt​=β2​vt−1​+(1−β2​)gt2​
ms=mt1(β1t) m_{s}=\frac{m_{t}}{1-(\beta_{1}^{t})} ms​=1−(β1t​)mt​​
vs=vt1(β2t) v_{s}=\frac{v_{t}}{1-(\beta_{2}^{t})} vs​=1−(β2t​)vt​​
θt+1=θtηvs+ϵms \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{v_{s}}+\epsilon} m_{s} θt+1​=θt​−vs​​+ϵη​ms​
Adam算法的全称是adaptive moment estimation,它吸收了RMSProp和Momentum算法的优点。其计算过程如下:

  • 计算第t次迭代的梯度;
  • 计算梯度的指数移动平均数,m0初始化为0。类似于Momentum算法,综合考虑之前时间步的梯度动量。β1系数为指数衰减率,控制动量与当前梯度的权重分配,默认为0.9;
  • 其次,计算梯度平方的指数移动平均数,v0初始化为0。β2系数为指数衰减率,控制前面的的梯度平方的影响情况,默认为0.999;
  • 由于m0初始化为0,会导致mt偏向于0,尤其在训练初期阶段。因此需要对梯度均值mt进行偏差纠正,降低偏差对训练初期的影响;
  • v0初始化为0导致训练初始阶段vt偏向0,对其进行纠正;
  • 更新权重参数θ,初始的学习率α乘以梯度均值与梯度方差的平方根之比。其中默认学习率α=0.001,ε=10^-8,避免除数变为0。
上一篇:android-如何在Xamarin上用SkiaSharp绘制日语文本


下一篇:c# – 如何将结构中的预定义颜色转换为颜色列表?