梯度下降算法

梯度下降算法

训练神经网络流程:
<1>获得数据;
<2>通过计算图前向传播,获得loss;
<3>反向传播计算梯度,这个梯度能告诉我们如何去调整权重,最终能够更好的分类图片;
<4>用计算出的梯度去更新参数

(1)、梯度下降算法

  • 批量梯度下降(Batch gradient descent)

旨在每次使用全量的训练集样本来更新模型参数,即:θ=θ−η⋅∇θJ(θ)
伪码如下:

for i in range(nb_epochs):
    params_grad = evaluate_gradient(loss_function,data,params)

nb_epochs是用户输入的最大迭代次数。使用全量的训练集样本计算损失函数loss_function的梯度params_grad,然后使用学习速率learning_rate朝着梯度相反方向去更新模型的每一个参数params。

批量梯度下降每次学习都使用整个训练集,因此其优点在于每次更新都会朝着正确的方向进行,最后能够保证收敛于极值点(凸函数收敛于全局极值点,非凸函数可能会收敛于局部极值点,属于凸理论的问题了),但是其缺点在于每次学习时间过长,并且如果训练集很大以至于需要消耗大量的内存,并且全量梯度下降不能进行在线模型参数更新。

  • 随机梯度下降(Stochastic gradient descent)

旨在每次从训练集中随机选择一个样本来进行学习,即:θ=θ−η⋅∇θJ(θ;xi;yi)
伪码如下:

for i in range(nb_epochs):
     np.random.shuffle(data)
     for example in data:
        params_grad = evaluate_gradient(loss_functon,example,params)

批量梯度下降算法每次都会使用全部训练样本,因此这些计算是冗余的,因为每次都使用完全相同的样本集。而随机梯度下降算法每次只随机选择一个样本来更新模型参数,因此每次的学习是非常快速的,并且可以进行在线更新。

我们可以对不同的参数方案和他们如何快速优化有一个直观的认识:

特别观察一下SGD,红色的那条线,从图中可以看出SGD实际上是所有方法中最慢的一个,所以在实际中很少应用它,我们可以使用更好的方案。
那我们来分析一下SGD的问题,是什么原因导致它的的速度这么慢?
举个栗子:

我们可以从水平方向上可以看出,它的梯度很是非常小的,因为处于在一个比较浅的水平里;但是垂直有很大的速率,因为它是一个非常陡峭的函数,所以出现了这种状况:

在这种情况下使用SGD,在水平方向上进行比较缓慢,而在垂直方向上进展的很快,所以产生了很大的上下震荡。

小批量梯度下降(Mini-batch gradient descent)

旨在综合了 batch 梯度下降与 stochastic 梯度下降,在每次更新速度与更新次数中间取得一个平衡,其每次更新从训练集中随机选择 m,m

for i in range(nb_epochs):
     np.random.shuffle(data)
     for batch in get_batches(data,batch_size=50):
         params_grad = evaluate_gradient(loss_function,batch,params)
         params = params - learning_rate * params_grad 

相对于随机梯度下降,Mini-batch梯度下降降低了收敛波动性,即降低了参数更新的方差,使得更新更加稳定。相对于全量梯度下降,其提高了每次学习的速度。并且其不用担心内存瓶颈从而可以利用矩阵运算进行高效计算。一般而言每次更新随机选择[50,256]个样本进行学习,但是也要根据具体问题而选择,实践中可以进行多次试验,选择一个更新速度与更次次数都较适合的样本数。mini-batch梯度下降可以保证收敛性,常用于神经网络中。

(2)、梯度下降优化算法

梯度下降算法存在的问题:
1. 选择一个合理的学习速率很难。如果学习速率过小,则会导致收敛速度很慢;如果学习速率过大,那么就会阻碍收敛,即在极值点附近会震荡。
学习速率调整(又称学习速率调度,Learning rate schedules),在每次更新过程中,改变学习速率,如退火。一般使用某种事先设定的策略或者在每次迭代中衰减一个较小的阈值。无论哪种调整方法,都需要事先进行固定设置,这便无法自适应每次学习的数据集特点。

2.模型所有的参数每次更新都是使用相同的学习速率。如果数据特征是稀疏的或者每个特征有着不同的取值统计特征与空间,那么便不能在每次更新中每个参数使用相同的学习速率,那些很少出现的特征应该使用一个相对较大的学习速率。

3.对于非凸目标函数,容易陷入那些次优的局部极值点中,如在神经网路中。那么如何避免呢。而更严重的问题不是局部极值点,而是鞍点。

  • Momentum

如果把要优化的目标函数看成山谷的话,可以把要优化的参数看成滚下山的石头,参数随机化为一个随机数可以看做在山谷的某个位置以0速度开始往下滚。目标函数的梯度可以看做给石头施加的力,由力学定律知:F=m∗a,所以梯度与石头下滚的加速度成正比。因而,梯度直接影响速度,速度的累加得到石头的位置,对这个物理过程进行建模,可以得到参数更新过程为

 # Momentum update
  v = momentum * v - learning_rate * dx # integrate velocity
  x += v # integrate position

代码中v指代速度,其计算过程中有一个超参数momentum,称为动量(momentum)。虽然名字为动量,其物理意义更接近于摩擦,其可以降低速度值,降低了系统的动能,防止石头在山谷的最底部不能停止情况的发生。如果没有momentum * v,那么小球就永远都不会停下了,会在平面上滚动,不会有能量的损失,损失函数就很难最小化。动量的取值范围通常为[0.5, 0.9, 0.95, 0.99],一种常见的做法是在迭代开始时将其设为0.5,在一定的迭代次数(epoch)后,将其值更新为0.99。

加上动量项就像从山顶滚下一个球,球往下滚的时候累积了前面的动量(动量不断增加),因此速度变得越来越快,直到到达终点。同理,在更新模型参数时,对于那些当前的梯度方向与上一次梯度方向相同的参数,那么进行加强,即这些方向上更快了;对于那些当前的梯度方向与上一次梯度方向不同的参数,那么进行削减,即这些方向上减慢了。即在陡峭的方向上削弱这些动荡,在一致的浅的方向激励此过程。因此可以获得更快的收敛速度与减少振荡。

  • Adagrad

Adagrad也是一种基于梯度的优化算法。

cache += dx**2
x += - learning_rate * dx / (np.sqrt(cache) + le-7)

相比于SGD,增加了个附加变量—-cache来放缩梯度,并且是不停的增加这一附加变量。这里的变量cache是一个联合矢量,和主向量是一样大的,因为cache在每一维度计算其相应梯度的平方和,我们将这些cache构造起来,然后逐项用这一函数去除以cache的平方,使得对每个参数自适应不同的学习速率,对稀疏特征,得到大的学习更新,对非稀疏特征,得到较小的学习更新,因此该优化算法适合处理稀疏特征数据。

So,举个栗子 :

Adagrad在垂直方向上的梯度会加到cache中,然后相应的会除以越来越大的数,所以在垂直方向上会得到越来越小的更新。当我们在垂直方向上看到许多大的梯度,Adagrad就会衰减学习速率,使垂直方向的更新步长越来越小。在水平方向上的梯度是很小的,所以分母会变小,相比于垂直方向,水平方向更新更快。这就是对每个参数自适应不同的学习速率,针对不同梯度方向的补偿措施。

  • Adam

Adam也是一种不同参数自适应不同学习速率方法,它是Adagrad算法和Momentum算法的结合:

# Adam
m = beta1 * m + (1-beta1) * dx
v  = beta2 * v  + (1-beta2) * (dx**2)
x += - learning_rate * m / (np.sqrt(v)) + le-7)

m与v分别是梯度的带权平均和带权有偏方差,初始为0向量,在衰减因子(衰减率)β1,β2接近于1时,m和v接近于0。为了改进这个问题,对m与v进行偏差修正(bias-corrected),偏差修正取决于时间步长t:

# Adam
m = beta1 * m + (1-beta1) * dx
v  = beta2 * v  + (1-beta2) * (dx**2)
m /= 1-beta1**t
v /= 1-beta2**t
x += - learning_rate * m / (np.sqrt(v)) + le-7)
  • 牛顿法

牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法就更快。如果更通俗地说的话,比如你想找一条最短的路径走到一个盆地的最底部,梯度下降法每次只从你当前所处位置选一个坡度最大的方向走一步,牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑你走了一步之后,坡度是否会变得更大。所以,可以说牛顿法比梯度下降法看得更远一点,能更快地走到最底部。

从几何上说,牛顿法就是用一个二次曲面去拟合你当前所处位置的局部曲面,而梯度下降法是用一个平面去拟合当前的局部曲面,通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的下降路径会更符合真实的最优下降路径。

红色的牛顿法的迭代路径,绿色的是梯度下降法的迭代路径。

迭代公式:

我们可以通过公式可以看出二阶收敛的优势,没有学习速率,没有超参数,只要知道方向和曲率,就能达到近似的最低值。但在实际应用中,牛顿法不是很受欢迎,在迭代公式中的H是指Hessian矩阵,比如你有1亿的数据,Hessian矩阵是1亿行和1亿列,计算量巨大。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章