优化函数知识点


优化函数

优化算法分为两大类
1)一阶优化算法
这种算法使用各个参数的梯度值来最小化(或最大化)损失函数L(x)。最常用的一阶优化算法是梯度下降。使用的偏导。
一阶有:
SGD、SGDM、NAG、AdaGrad(自适应梯度)、RMSProp(均方差传播)、Adam、Nadam

2)二阶优化算法
二阶优化算法使用了二阶导数(也叫做Hessian方法)来优化(最小化、最大化)损失函数。由于二阶导数的计算成本很高,所以这种方法并没有广泛使用。
二阶有:
牛顿、拟牛顿、共轭梯度法


BGD批量梯度下降法

计算整个数据集所有样本的梯度,来进行更新。权重只会进行一次更新,因此在处理大型数据集时速度很慢且难以控制,甚至导致内存溢出;另一方面,在训练大型数据集时存在冗余的权重更新。
权重更新的快慢是由学习率η决定的,并且可以在凸面误差曲面中收敛到全局最优值,在非凸曲面中可能趋于局部最优值。
优点:精度高。目标函数(损失函数)为凸函数时,可保证收敛至全局最优解,非凸函数可以得到局部最优解。全部样本进行训练,代表的求解方向更准确。
缺点:计算速度缓慢,不允许新样本中途进入


SGD随机梯度下降法

每次从数据集中随机挑选一个样本进行计算梯度并更新。频繁的更新使得参数间具有高方差,损失函数会以不同的强度波动。这实际上是一件好事,因为它有助于我们发现新的和可能更优的局部最优值。
优点:计算速度快
缺点:准确率低。计算结果不易收敛,可能会陷入局部最优解中。不利于并行计算


mini-BGD小批次梯度下降法

每次计算batch内所有样本的梯度,进行更新。
小批量梯度下降法即保证了训练的速度,又能保证最后收敛的准确率,目前的SGD默认是小批量梯度下降算法
优点:计算速度快、收敛稳定。融合了BGD和SGD的优点。可以并行计算。
缺点:batch的选择


使用梯度下降及其变体时面临的挑战

很难选择出合适的学习率。太小的学习率会导致网络收敛过于缓慢,而学习率太大可能会影响收敛,并导致损失函数在最小值上波动,甚至出现梯度发散。
此外,相同的学习率并不适用于所有的参数更新。如果训练集数据很稀疏,且特征频率非常不同,则不应该将其全部更新到相同的程度,但是对于很少出现的特征,应使用更大的更新率。
在神经网络中,最小化非凸误差函数的另一个关键挑战是避免陷于多个其他局部最小值中。实际上,问题并非源于局部极小值,而是来自鞍点,即一个维度向上倾斜且另一维度向下倾斜的点。这些鞍点通常被相同误差值的平面所包围,这使得SGD算法很难脱离出来,因为梯度在所有维度上接近于零。

为什么选择动量类梯度下降
当我们将一个小球从山上滚下来,没有阻力时,它的动量会越来越大,但是如果遇到了阻力,速度就会变小,动量优化法就是借鉴此思想,使得梯度方向在不变的维度上,参数更新变快,梯度有所改变时,更新参数变慢,这样就能够加快收敛并且减少动荡。
因为参数是带有方向的,不单单是数值,所以可以这样形容。

目前深度学习的优化器大都具备动量自适应,但是在最后精调阶段,动量过大也许会让网络又跳出了最优区域,适度的减小动量参数,可以让后期网络缓慢的朝着更优的方向优化。


momentum动量梯度下降法

算法思想:参数更新时在一定程度上保留之前更新的方向,同时又利用当前batch的梯度微调最终的更新方向,简言之就是通过积累之前的动量来加速当前的梯度。当前时刻的梯度与历史时刻梯度方向相似,这种趋势在当前时刻则会加强;要是不同,则当前时刻的梯度方式减弱。假设m_t表示t时刻的梯度,β表示动量因子,通常取值0.9或者近似值,η为学习率,在SGD的基础上增加动量,则参数更新公式如下:
m t + 1 = β ∗ m t + ( 1 − β ) ∗ J ( θ ) θ i + 1 = θ i − η ∗ m t + 1 m_{t+1}=β*m_t+(1-β)*J(θ) \\ θ_{i+1}=θ_i-η*m_{t+1} mt+1=βmt+(1β)J(θ)θi+1=θiηmt+1
梯度方向改变时,momentum能够降低参数更新速度,从而减少震荡;在梯度方向相同时,momentum可以加速参数更新,从而加速收敛。总而言之,momentum能够加速SGD收敛,抑制震荡。


NAG(Nesterov accelerated gradient)

momentum保留了上一刻的梯度没有改变,NAG对梯度进行了一个矫正,即梯度变成了J(θ-αm_t)。意思是我既然知道这一次一定会走之前动量的步伐,为什么还要在这里更新呢?所以它就走到下一个参数的位置,再更新。即梯度是根据动量法之后的参数进行计算的。
m t + 1 = β ∗ m t + ( 1 − β ) ∗ J ( θ − β ∗ m t ) m_{t+1}=β*m_t+(1-β)*J(θ-β*m_t) mt+1=βmt+(1β)J(θβmt)

NAG本质上是多考虑了目标函数的二阶导信息,其实所谓“往前看”的说法,在牛顿法这样的二阶方法中也是经常提到的,比喻起来是说“往前看”,数学本质上则是利用了目标函数的二阶导信息。
困在局部最优的沟壑里面震荡。想象一下你走到一个盆地,四周都是略高的小山,你觉得没有下坡的方向,那就只能待在这里了。可是如果你爬上高地,就会发现外面的世界还很广阔。因此,我们不能停留在当前位置去观察未来的方向,而要向前一步、多看一步、看远一些。


自适应学习率优化算法

在机器学习中,学习率是一个非常重要的超参数,但是学习率是非常难确定的,虽然可以通过多次训练来确定合适的学习率,但是一般也不太确定多少次训练能够得到最优的学习率,玄学事件,对人为的经验要求比较高,所以是否存在一些策略自适应地调节学习率的大小,从而提高训练速度


AdaGrad

做法:将每一个参数的每一次迭代的梯度取平方,然后累加并开方得到r,最后用全局学习率除以 r,作为学习率的动态更新。也就是说,让历史梯度变化很大的参数,学习率逐渐减小,因为梯度变化大,h值越大。ϵ防止除以0。
h = h + J ( θ ) ∗ J ( θ ) θ = θ − η ϵ + √ h J ( θ ) h=h+J(θ)*J(θ) \\ θ=θ-\frac{η}{ϵ+√h} J(θ) h=h+J(θ)J(θ)θ=θϵ+hηJ(θ)
AdaGrad即adaptive gradient,是一种自适应学习率的梯度法。它通过记录并调整每次迭代过程中的前进方向和距离,使得针对不同问题都有一套自适应学习率的方法。Adagrad最大的优势是不需要手动来调整学习率,但与此同时会降低学习率。
AdaGrad可以自动变更学习速率,只是需要设定一个全局的学习速率,但是这并非是实际学习速率,实际的速率是与以往参数的模之和的开方成反比的。
核心思想:
对于频繁出现的参数使用更小的更新速率,对于不频繁出现的参数使用更大的更新速率。
正因为如此,该优化函数脚适用于稀疏的数据,比如在Google从YouTube视频上识别猫时,该优化函数大大提升了SGD的鲁棒性。在训练GloVe词向量时该优化函数更加适用。
分析:
1)从AdaGrad算法中可以看出,随着算法不断迭代,r会越来越大,整体的学习率会越来越小。所以,一般来说AdaGrad算法一开始是激励收敛,到了后面就慢慢变成惩罚收敛,速度越来越慢
2)还是需要自己手动指定初始学习率,而且由于分母中对历史梯度一直累加,学习率将逐渐下降至0,并且如果初始梯度很大的话,会导致整个训练过程的学习率一直很小,从而导致学习时间变长。


RMSProp(均方差传播)

AdaGrad算法在前期可能会有很大的梯度,自始至终都保留了下来,这会使得后期的学习率过小。RMSProp在这个基础之上,加入了平方梯度的衰减项,只能记录最近一段时间的梯度,在找到碗状区域时能够快速收敛。相当于减小了学习率。实际上就是给AdaGrad的求和变成了动量。
S J ( θ ) = β ∗ S J ( θ ) + ( 1 − β ∗ J ( θ ) 2 ) θ = θ − η S J ( θ ) + ϵ J ( θ ) S_{J(θ)} =β*S_{J(θ)} +(1-β*J(θ)^2) \\ θ=θ-\frac{η }{\sqrt{S_{J(θ) }}+ϵ}J(θ) SJ(θ)=βSJ(θ)+(1βJ(θ)2)θ=θSJ(θ) +ϵηJ(θ)
可以使用更大的学习率。
在梯度值较大的方向进行适当的减小步伐,在梯度值较小的方向适当增大步伐,没有考虑方向。


Adam

Adam即Adaptive Moment Estimation,是能够自适应时刻的估计方法,能够针对每个参数,计算自适应学习率。这是一种综合性的优化方法,在机器学习实际训练中,往往能够取得不错的效果。结合了梯度的一阶矩估计和二阶矩估计。实际就是将RMSProp和Momentum结合
m t + 1 = β m ∗ m t + ( 1 − β m ) ∗ J ( θ ) S J ( θ ) = β s ∗ S J ( θ ) + ( 1 − β s ∗ J ( θ ) 2 ) m t + 1 c o r r e c t e d = m t + 1 1 − β m t + 1 S J ( θ ) c o r r e c t e d = S J ( θ ) 1 − β s t + 1 θ = θ − η ∗ m t + 1 c o r r e c t e d √ S J ( θ ) c o r r e c t e d + ϵ m_{t+1}=β_m*m_t+(1-β_m)*J(θ)\\ S_J(θ) =β_s* S_J(θ) +(1-β_s* J(θ)^2)\\ m_{t+1}^{corrected}=\frac{m_{t+1}}{1-β_m^{t+1} }\\ S_J(θ)^{corrected}=\frac{S_J(θ) }{1-β_s^{t+1} }\\ θ=θ-η*\frac{m_{t+1}^{corrected}}{√S_J(θ)^{corrected}+ϵ} mt+1=βmmt+(1βm)J(θ)SJ(θ)=βsSJ(θ)+(1βsJ(θ)2)mt+1corrected=1βmt+1mt+1SJ(θ)corrected=1βst+1SJ(θ)θ=θηSJ(θ)corrected+ϵmt+1corrected
其中β_m^{t+1}的t+1表示t+1次方。
优点
1)经过偏置校正后,每一次迭代都有确定的范围,使得参数比较平稳。善于处理稀疏梯度和非平稳目标。
2)对内存需求小
3)对不同内存计算不同的学习率
4)更新的步长能够被限制在大致的范围内(初始学习率)
5)能自然地实现步长退火过程(自动调整学习率)
6)很适合应用于大规模的数据及参数的场景
7)适用于不稳定目标函数
8)适用于梯度稀疏或梯度存在很大噪声的问题



综合

对于稀疏数据,尽量使用学习率可自适应的优化方法,不用手动调节,而且最好采用默认值。
SGD通常训练时间更长,但是在好的初始化和学习率调度方案的情况下(很多论文都用SGD),结果更可靠。
如果在意更快的收敛,并且需要训练较深较复杂的网络时,推荐使用学习率自适应的优化方法。
Adadelta,RMSprop,Adam是比较相近的算法,在相似的情况下表现差不多 。Adam 就是在 RMSprop 的基础上加了 bias-correction 和 momentum,随着梯度变得稀疏,Adam 比 RMSprop 效果会好。整体来讲,Adam是最好的选择。
Adam等自适应学习率算法对于稀疏数据具有优势,且收敛速度很快;但精调参数的SGD(+Momentum)往往能够取得更好的最终结果。先用Adam再用Momentum?


batch_size的影响

一般来说,在合理的范围之内,越大的 batch_size 使下降方向越准确,震荡越小,内存利用率提高,一个epoch的时间减少;batch_size 如果过大,则可能会出现局部最优的情况。小的bath_size引入的随机性更大,难以达到收敛,极少数情况下可能会效果变好。
因为当前的框架都是将batch内所有样本loss求平均,batch太小,这个平均值就波动比较大,梯度震荡;batch太大,每次的平均值会差别不大,不同batch的梯度方向没有任何变化,容易陷入局部极小值。
一般设置在256以下,256以上效果就不好了。因为GPU对2的幂可能比较友好,所以设置为2的倍数。


在合理范围内,增大Batch_Size有何好处?

1)内存利用率提高了,大矩阵乘法的并行化效率提高。
2)跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
3)在一定范围内,一般来说Batch_Size越大,其确定的下降方向越准,引起训练震荡越小。


盲目增大 Batch_Size 有何坏处?

1)内存利用率提高了,但是内存容量可能撑不住了。
2)跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
3)Batch_Size增大到一定程度,其确定的下降方向已经基本不再变化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值