用于评估机器学习模型的就是损失函数,我们训练的目的基本上都是最小化损失,这个最小化的方式就要用优化算法了,机器学习中最常用的就是梯度下降算法。
导数、方向导数和梯度
要了解梯度下降算法是什么首要知道梯度是什么,导数和方向导数又是了解梯度的前提。
导数
导数反映的是函数y=f(x)在某一点处沿x轴正方向的变化率,如果f’(x)>0,说明f(x)的函数值在x点沿x轴正方向是趋于增加的;如果f’(x)<0,说明f(x)的函数值在x点沿x轴正方向是趋于减少的。
方向导数
方向导数是某一点在某一趋近方向上的导数值,即导数或偏导数是函数在x轴正方向的变化率,而方向导数是函数在其他特定方向上的变化率。
梯度
梯度的提出只为回答一个问题: 函数在变量空间的某一点处,沿着哪一个方向有最大的变化率?
函数在某一点的梯度是这样一个向量,它的方向与取得最大方向导数的方向一致,而它的模为方向导数的最大值。
也就是说梯度即函数在某一点最大的方向导数,函数沿梯度方向函数有最大的变化率。
知道了函数沿梯度方向有最大的变化率,那么在机器学习中我们为了最小化损失,在优化目标函数的时候就可以沿着负梯度方向去减小函数值,以此达到我们的优化目标,这就是梯度下降算法。
梯度下降算法
梯度下降算法(Gradient Descent)是通过沿着目标函数J(θ)参数θ∈ℜ的梯度相反方向−∇θJ(θ)来不断更新模型参数来到达目标函数的极小值点(收敛),更新步长为η(这个步长又称为学习率)。
更新参数的公式如下:
∇θJ(θ)为参数的梯度
根据计算目标函数J(θ)采用数据量的不同(每次学习(更新模型参数)使用的样本个数的不同),梯度下降算法又可以分为批量梯度下降算法(Batch Gradient Descent),随机梯度下降算法(Stochastic Gradient Descent)和小批量梯度下降算法(Mini-batch Gradient Descent)。
批量梯度下降算法(Batch Gradient Descent)
每次使用全量的训练集样本来更新模型参数。具体做法是:每次使用全部训练集样本计算损失函数loss_function的梯度params_grad,然后使用学习速率learning_rate朝着梯度相反方向去更新模型的每个参数params。
优点:
每次更新都会朝着正确的方向进行,最后能够保证收敛于极值点(凸函数收敛于全局极值点,非凸函数可能会收敛于局部极值点)
缺点:
每次学习时间过长,并且如果训练集很大以至于需要消耗大量的内存,并且全量梯度下降不能进行在线模型参数更新。
随机梯度下降算法(Stochastic Gradient Descent)
随机梯度下降算法每次从训练集中随机选择一个样本来进行学习
优点:
每次只随机选择一个样本来更新模型参数,因此每次的学习是非常快速的,并且可以进行在线更新(得到了一个样本,就可以执行一次参数更新)。
缺点:
每次更新可能并不会按照正确的方向进行,因此可以带来优化波动(扰动)。由于波动,因此会使得迭代次数(学习次数)增多,即收敛速度变慢。不过最终其会和全量梯度下降算法一样,具有相同的收敛性,即凸函数收敛于全局极值点,非凸损失函数收敛于局部极值点(随机梯度下降所带来的波动有个好处就是,对于类似盆地区域(即很多局部极小值点)那么这个波动的特点可能会使得优化的方向从当前的局部极小值点跳到另一个更好的局部极小值点,这样便可能对于非凸函数,最终收敛于一个较好的局部极值点,甚至全局极值点。 )。
小批量梯度下降算法(Mini-batch Gradient Descent)
小批量选择了折中的办法,每次选择m个样本进行学习
相对于随机梯度下降,Mini-batch梯度下降降低了收敛波动性,即降低了参数更新的方差,使得更新更加稳定。相对于全量梯度下降,其提高了每次学习的速度。并且其不用担心内存瓶颈从而可以利用矩阵运算进行高效计算。
梯度下降算法的问题
不能保证全局收敛
梯度下降算法针对凸优化问题原则上是可以收敛到全局最优的,因为此时只有唯一的局部最优点。而实际上深度学习模型是一个复杂的非线性结构,一般属于非凸问题,这意味着存在很多局部最优点(鞍点),采用梯度下降算法可能会陷入局部最优。
学习率问题
选择一个合适的学习率很难
如果学习速率过小,则会导致收敛速度很慢。如果学习速率过大,那么其会阻碍收敛,即在极值点附近会振荡。
学习速率调整无法自适应
学习速率调整(又称学习速率调度,Learning rate schedules)试图在每次更新过程中,改变学习速率,如退火。一般使用某种事先设定的策略或者在每次迭代中衰减一个较小的阈值。无论哪种调整方法,都需要事先进行固定设置,这边便无法自适应每次学习的数据集特点。
模型所有的参数每次更新都是使用相同的学习速率
模型所有的参数每次更新都是使用相同的学习速率。如果数据特征是稀疏的或者每个特征有着不同的取值统计特征与空间,那么便不能在每次更新中每个参数使用相同的学习速率,那些很少出现的特征应该使用一个相对较大的学习速率。
梯度下降优化算法
由于梯度下降算法存在上述问题,而理想的梯度下降算法要满足两点:收敛速度要快;能全局收敛。因此出现了很多解决上诉问题的一些梯度优化方法。
其实这些优化算法都是基于学习率上的改变。
冲量梯度下降算法 Momentum
冲量梯度算法参数更新时不仅考虑当前梯度值,动量在参数更新项中加上一次更新量(即动量项),在学习率上来讲就是不进加这一次的学习率还要加上以前的,所以会更快的到达global minimum。公式如下:
其中动量项超参数γ<1一般是小于等于0.9。
momentum基于这样一个物理事实:将一个小球从山顶滚下,其初始速率很慢,但在加速度作用下速率很快增加(也就是累积了前面的动量(动量不断增加),因此速度变得越来越快),并最终由于阻力的存在达到一个稳定速率。
在更新模型参数时,对于那些当前的梯度方向与上一次梯度方向相同的参数,那么进行加强,即这些方向上更快了;对于那些当前的梯度方向与上一次梯度方向不同的参数,那么进行削减,即这些方向上减慢了。因此可以获得更快的收敛速度与减少振荡。
动量能够解决的问题:
如果在峡谷地区(某些方向较另一些方向上陡峭得多,常见于局部极值点),SGD会在这些地方附近振荡,从而导致收敛速度慢。这种情况下,可用动量解决。
NAG算法 (Nesterov Accelerated Gradient)
NAG算法是冲量梯度下降算法的改进版本,其速度更快。其变化之处在于计算“超前梯度”(下一次参数在的位置)更新冲量项,也就是加上动量项的基础上,在计算参数的梯度时,在损失函数中减去了动量项,即计算,这种方式预估了下一次参数所在的位置。遵循的原理为:从山顶往下滚的球会盲目地选择斜坡。更好的方式应该是在遇到倾斜向上之前应该减慢速度。
具体公式如下:
Adagrad
Adagrad是一种学习速率自适应的梯度下降算法。在训练迭代过程,其学习速率是逐渐衰减的,经常更新的参数其学习速率衰减更快。
在前述中,每个模型参数使用相同的学习速率η,而Adagrad在每一个更新步骤中对于每一个模型参数使用不同的学习速率,设第t次更新步骤中,目标函数的参数梯度为,即:
Adagrad对每一个参数使用不同的学习速率,其更新方程为:
其中,是一个对角矩阵,其中第i行的对角元素为过去到当前第i个参数的梯度的平方和,是一个平滑参数,为了使得分母不为0(通常ϵ=1e−8)
写成向量点乘为:
s就是梯度平方的积累量,在进行参数更新时,学习速率要除以这个积累量的平方根,其中加上一个很小值是为了防止除0的出现。由于是该项逐渐增加的,那么学习速率是衰减的。
由于比较陡的方向梯度比较大,其学习速率将衰减得更快,这有利于参数沿着更接近坡底的方向移动,从而加速收敛。但是,学习速率实际上是不断衰减的,这会导致一个很大的问题,就是训练后期学习速率很小,导致训练过早停止,因此在实际中AdaGrad一般不会被采用。
Adadelta和RMSprop
Adadelta和RMSprop都是针对Adagrad学习速率衰减过快问题作出的改进
RMSprop
RMSprop类似Momentum思想,引入一个超参数,在积累梯度平方项进行衰减:
可以认为仅仅对距离时间较近的梯度进行积累,其中一般取值0.9,其实这样就是一个指数衰减的均值项,减少了出现的爆炸情况,因此有助于避免学习速率很快下降的问题。同时Hinton也建议学习速率设置为0.001。
Adadelta
改进思路和RMSprop很像,但是其背后是基于一次梯度近似代替二次梯度的思想。
其改进了三处,一是使用了窗口w;二是对于参数梯度历史窗口序列(不包括当前)不再使用平方和,而是使用均值代替;三是最终的均值是历史窗口序列均值与当前梯度的时间衰减加权平均。
Adam (Adaptive Moment Estimation)
Adam也是一种不同参数自适应不同学习速率方法,其结合了Momentum和RMSprop算法的思想。相比Momentum算法,其学习速率是自适应的,而相比RMSprop,其增加了冲量项。如下:
可见,第一个m的公式就是之前momentum的冲量项,s是RMSprop的,由于和的初始值一般设置为0,在训练初期其可能较小,第三和第四项主要是为了放大它们。最后一项是参数更新。其中超参数的建议值是:=0.9,=0.999,。
| 梯度优化算法 | Momentum与NAG | Adagrad、Adadelta和RMSprop | Adam |
|---|---|---|---|
| 特点 | 根据损失函数的斜率做到自适应更新来加速收敛 | 不同参数学习率自适应 | 不同参数学习速率自适应 |
| 增加 | 冲量项 | 梯度平方积累量 | 冲量和梯度平方 |
为了理清思路我将梯度优化算法总结成了下图,用语言表述为:由于梯度下降算法有种种缺点,因此有很多基于梯度下降进行改进的算法。基于从山上滚小球的原理,在基础的梯度下降中增加了动量项得到了Momentum,然后基于不是盲目选择下坡,而是要在遇到倾斜向上时减慢速度的原来,在Momentum增加了计算下一次参数所在位置,得到了NAG;考虑到传统梯度下降算法学习率一直不变造成了很多问题,因此通过增加梯度平方积累量,以达到学习速率自适应,从而得到了Adagrad算法。由于学习速率减小过快会导致提前终止,为了解决这一问题又产生了Adadelta和RMSprop。 最后的Adam是比较好的算法,他结合了Momentum和RMSprop。
参考:https://blog.csdn.net/heyongluoyao8/article/details/52478715
https://blog.csdn.net/u013709270/article/details/78667531