Mini-batch梯度下降法
- 批梯度下降时,每一次迭代代价函数都会降低(如果某一次不是,说明出问题了,可能要改变学习率),而mini-batch梯度下降时,不一定每次都降低,但是总的趋势是下降的;
- Mini-batch的大小设为m(总样本数)时,变成了batch梯度下降(训练慢当样本总数大时),当设为1,变成了随机梯度下降(这时没能很好利用多样本的向量化的优势,也会导致变慢)。所示实际中选择不大不小的mini-batch尺寸,下降速度达到最快;
- 不管是随机梯度下降还是mini-batch梯度下降都不会达到收敛,所以后期需要减小学习率来使其趋向收敛;
- 当样本数小于2000时可直接使用batch梯度下降,当样本数很大时,一般把mini-batch的大小设为2的n次方,比如64,126,512等,这样是考虑到电脑内存设置和使用方法;
- 在调参mini-batch的大小时常常设置2的不同次方。
指数加权平均数
- 公式:
v t = β v t − 1 + ( 1 − β ) θ t v_t = \beta v_{t-1} + (1 - \beta)\theta_t vt=βvt−1+(1−β)θt
{ v 100 = 0.9 v 99 + 0.1 θ 100 v 99 = 0.9 v 98 + 0.1 θ 99 v 98 = 0.9 v 97 + 0.1 θ 98 v 100 = 0.9 v 99 + 0.1 θ 100 ⇒ v 100 = 0.1 θ 100 + 0.1 ∗ 0.9 θ 99 + 0.1 ∗ ( 0.9 ) 2 θ 98 + 0.1 ∗ ( 0.9 ) 3 θ 97 + . . . \begin{cases} v_{100} = 0.9v_{99} + 0.1 \theta_{100} \\ v_{99} = 0.9v_{98} + 0.1 \theta_{99} \\ v_{98} = 0.9v_{97} + 0.1 \theta_{98} \\ v_{100} = 0.9v_{99} + 0.1 \theta_{100}\end{cases} \Rightarrow v_{100} = 0.1\theta_{100} + 0.1 * 0.9 \theta_{99} + 0.1 * (0.9)^2 \theta_{98} + 0.1 * (0.9)^3 \theta_{97} + ... ⎩⎪⎪⎪⎨⎪⎪⎪⎧v100=0.9v99+0.1θ100v99=0.9v98+0.1θ99v98=0.9v97+0.1θ98v100=0.9v99+0.1θ100⇒v100=0.1θ100+0.1∗0.9θ99+0.1∗(0.9)2θ98+0.1∗(0.9)3θ97+... - vt是迭代得到的,最初令其为0,一步步迭代计算,但最后是一种平均数,我们用这种平均数来代替 θ \theta θ。可以认为我们由原来以往变化趋势乘以一个权重 β \beta β,和当下的变化乘权重 1 − β 1-\beta 1−β,这样可以两者之和表现出一部分现在的变化,同时也更表现出了以往的一种应该发展的趋势;
- 指数加权平局数公式的好处之一:它只占用极少的内存,电脑内存只占一行数字而已,不断的覆盖就可以了。当然它不是最好的,也不是最精确的。如果要计算移动窗,可以直接计算过去10天或者50天的和,再除以10或者50就好,如此往往得到更好的估测。但缺点是,必须占用更多的内存,执行更加复杂;
- 指数加权平均的求解过程实际上是一个递推的过程,那么这样就会有一个非常大的好处,每当我要求从0到某一时刻(n)的平均值的时候,我并不需要像普通求解平均值的作为,保留所有的时刻值,类和然后除以n。而是只需要保留0-(n-1)时刻的平均值和n时刻的温度值即可。也就是每次只需要保留常数值,然后进行运算即可,这对于深度学习中的海量数据来说,是一个很好的减少内存和空间的做法;
- 指数加权平均数的偏差修正,即按照之前的公式算出
v
t
v_t
vt之后,再除以
1
−
β
t
1-\beta^{t}
1−βt,如下所示:
{ v t = β v t − 1 + ( 1 − β ) θ t v t c o r r e c t = v t 1 − β t \begin{cases}v_t = \beta v_{t-1} + (1 - \beta)\theta_t \\ v_t^{correct} = \frac{v_t}{1 - \beta^{t}}\end{cases} {vt=βvt−1+(1−β)θtvtcorrect=1−βtvt
Momentum
- momentum梯度下降总是会比标准的梯度下降要快。基本的想法是,计算梯度的指数加权平均数,并利用该梯度更新权重:
{ v d w = β v d w + ( 1 − β ) d w v d b = β v d b + ( 1 − β ) d b w = w − α v d w , b = b − α v d b \begin{cases}v_{dw} = \beta v_{dw} + (1 - \beta)dw \\ v_{db} = \beta v_{db} + (1 - \beta)db \\ w = w - \alpha v_{dw}, b = b - \alpha v_{db}\end{cases} ⎩⎪⎨⎪⎧vdw=βvdw+(1−β)dwvdb=βvdb+(1−β)dbw=w−αvdw,b=b−αvdb - 假如将算法的优化比作小球从山上下降的过程,那么梯度下降方法就像是小球每次在某 一个位置,先找到眼下坡度最陡峭的地方然后从那里下降,之后到达新的位置,速度减为零,重新寻找最陡峭的地方,如此以往到达最底部。而动量法则是每次保留上次下降时的速度,然后在新的位置,寻找到最陡峭的地方,结合上次的速度下降。所以动量法在梯度下降的基础上累计了之前梯度方向的衰减值,并且结合累计的梯度方向和新计算的梯度方向共同决定下一步的移动方向,与经典的梯度下降算法不同的是,动量法更倾向于保持在相同方向上前进,以防止震荡的产生;
- 梯度下降算法每次迭代就重新计算梯度方向,并沿着新的梯度方向下降,而动量法则是在上一次梯度的基础上进行修正,得到新的下降方向,需要指出的是动量法在一定程度上克服了海森矩阵的病态问题;
- 是否进行偏差修正影响不大, β \beta β取0.9是一个比较好的参数,学习率α会随之β的修改做一定的修改;
- 当本次梯度下降的方向与上次更新量的方向相同时,上次的更新量能够对本次的搜索起到一个正向加速的作用,当本次梯度下降的方向与上次更新量的方向相反时,上次的更新量能够对本次的搜索起到一个减速的作用。
RMSprop
-
RMSprop 算法采用移动平均,以指数衰减的速度丢弃遥远的历史梯度,可以削弱某些维度梯度更新波动较大的情况:
{ S d w = β S d w + ( 1 − β ) d w 2 S d b = β S d b + ( 1 − β ) d b 2 w = w − α d w S d w + ϵ , b = b − α d b S d b + ϵ \begin{cases}S_{dw} = \beta S_{dw} + (1 - \beta)dw^2 \\ S_{db} = \beta S_{db} + (1 - \beta)db^2 \\ w = w - \alpha \frac{dw}{\sqrt{S_{dw}} + \epsilon}, b = b - \alpha \frac{db}{\sqrt{S_{db}} + \epsilon} \end{cases} ⎩⎪⎨⎪⎧Sdw=βSdw+(1−β)dw2Sdb=βSdb+(1−β)db2w=w−αSdw+ϵdw,b=b−αSdb+ϵdb -
同时引入了一个新的超参数 β \beta β,用于移动平均,一般设为0.9。RMSprop将微分项进行平方,然后使用平方根进行梯度更新,同时为了确保算法不会除以0,平方根分母中在实际使用会加入一个很小的值 ϵ \epsilon ϵ。
Adam
- Adam(Adaptive Moment Estimation)优化算法的基本思想就是将 Momentum 和 RMSprop 结合起来形成的一种适用于不同深度学习结构的优化算法:
{ v d w = β 1 v d w + ( 1 − β 1 ) d w v d b = β 1 v d b + ( 1 − β 1 ) d b S d w = β 2 S d w + ( 1 − β 2 ) d w 2 S d b = β 2 S d b + ( 1 − β 2 ) d b 2 v d w c o r r e t = v d w 1 − β 1 t , v d b c o r r e t = v d b 1 − β 1 t S d w c o r r e t = S d w 1 − β 2 t , S d b c o r r e t = S d b 1 − β 2 t w = w − α v d w c o r r e t S d w c o r r e t + ϵ , b = b − α v d b c o r r e t S d b c o r r e t + ϵ \begin{cases} v_{dw} = \beta_1 v_{dw} + (1 - \beta_1)dw \\ v_{db} = \beta_1 v_{db} + (1 - \beta_1)db \\ S_{dw} = \beta_2 S_{dw} + (1 - \beta_2)dw^2 \\ S_{db} = \beta_2 S_{db} + (1 - \beta_2)db^2 \\ v_{dw}^{corret} = \frac{v_{dw}}{1- \beta_1^{t}}, v_{db}^{corret} = \frac{v_{db}}{1- \beta_1^{t}} \\ S_{dw}^{corret} = \frac{S_{dw}}{1- \beta_2^{t}}, S_{db}^{corret} = \frac{S_{db}}{1- \beta_2^{t}} \\ w = w - \alpha \frac{v_{dw}^{corret}}{\sqrt{S_{dw}^{corret} + \epsilon}}, b = b - \alpha \frac{v_{db}^{corret}}{\sqrt{S_{db}^{corret} + \epsilon}} \end{cases} ⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧vdw=β1vdw+(1−β1)dwvdb=β1vdb+(1−β1)dbSdw=β2Sdw+(1−β2)dw2Sdb=β2Sdb+(1−β2)db2vdwcorret=1−β1tvdw,vdbcorret=1−β1tvdbSdwcorret=1−β2tSdw,Sdbcorret=1−β2tSdbw=w−αSdwcorret+ϵvdwcorret,b=b−αSdbcorret+ϵvdbcorret - 参数更新的时候,注意此时一般的 β 1 \beta_1 β1取0.9, β 2 \beta_2 β2取0.999。
AdaBound
它给学习率划出动态变化的界限,让实现从Adam到SGD的渐进和平滑过渡,让模型在开始阶段有和Adam一样快的训练速度,后期又能保证和SGD一样稳定的学习率。
这种思路是受到2017年Salesforce的研究人员的启发。他们通过实验发现,Adam后期的学习率太低影响了收敛结果。如果控制一下Adam的学习率的下限,实验结果会好很多。
对学习率的控制就和梯度裁剪差不多。在防止梯度爆炸问题上,我们可以剪掉大于某个阈值的梯度。同样的,我们也可以剪裁Adam学习率实现AdaBound。
在上面的公式中,学习率被限制在下限
η
l
η_l
ηl 和上限
η
u
η_u
ηu之间。当
η
l
=
η
u
=
α
η_l = η_u = α
ηl=ηu=α时,就是SGD算法;当
η
l
=
0
η_l=0
ηl=0,
η
u
=
∞
η_u=∞
ηu=∞时,就是Adam算法。
为了实现从Adam到SGD的平滑过渡,让
η
l
η_l
ηl和
η
u
η_u
ηu变成随时间变化的函数:
η
l
η_l
ηl 递增从0收敛到α,
η
u
η_u
ηu从∞递减收敛到α。
在这种情况下,AdaBound开始时就像Adam一样训练速度很快,随着学习率边界越来越受到限制,它又逐渐转变为SGD。
学习率衰减
- 常用:
α = 1 1 + d e c a y r a t e ∗ e p o c h _ n u m α 0 \alpha = \frac{1}{1 + decay_rate * epoch\_num}\alpha_0 α=1+decayrate∗epoch_num1α0 - 指数衰减:
α = 0.9 5 e p o c h _ n u m α 0 \alpha = 0.95^{epoch\_num}\alpha_0 α=0.95epoch_numα0 - 其它:
α = k e p o c h _ n u m α 0 \alpha = \frac{k}{epoch\_num}\alpha_0 α=epoch_numkα0 - 离散衰减
局部最优问题
- 在低维(如二维)可能陷入局部最优;
- 但是在高维中,比如20000维,陷入局部最优的概率是 2 − 20000 2^{-20000} 2−20000(即每一维度都梯度为零,几乎不可能),所以更多的时候是出现处在鞍点上(鞍点处,在某些方向上是峰顶,在其他方向上是谷底);
- 存在的问题是:在平稳端学习缓慢,上面提到的算法如Adam,能够更快的走出平稳区。