梯度下降优化方法总结

来源:互联网 发布:tower for mac 破解 编辑:程序博客网 时间:2024/04/30 07:17


原文地址

参考并翻译自Sebastian Ruder博士的总结文章An overview of gradient descent optimization algorithms。


梯度下降方法是目前最流行的神经网络优化方法,现在主流的深度学习框架(caffe,keras,MXNET等)都包含了若干种梯度下降算法。虽然我们可以把它们看成黑盒直接使用,但是在不同场合下相同的算法可能有着很大的性能差异,因此,了解这些算法各自内在的原理可以帮助我们更好地训练网络。

基本梯度下降算法

有三种基本的梯度下降算法,他们的主要区别在于用于计算一次目标函数梯度的样本数量。

批量梯度下降(Batch graduebt descent)

批量梯度下降算法使用整个训练集计算目标函数的梯度并更新参数θ,具体公式为

θ=θηθJ(θ)

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

因为每更新一次参数就需要计算整个数据集,所以批量梯度下降算法十分缓慢而且难以存放在内存中计算,更致命的是,使用批量梯度下降的算法无法在线更新。

随机梯度下降(Stochatic gradient decent, SGD)

与批量梯度下降方法不同,随机梯度下降方法一次只使用一个样本进行目标函数梯度计算,它的公式为

θ=θηθJ(θ;x(i),y(i))

因为每次只计算一个样本,所以SGD计算非常快并且适合线上更新模型。但是,频繁地更新参数也使得目标函数抖动非常厉害。

SGD频繁地参数更新可以使算法跳出局部最优点,更可能寻找到接近全局最优的解。
SGD代码如下:

for i in range(nb_epochs):  np.random.shuffle(data)  for example in data:    params_grad = evaluate_gradient(loss_function, example, params)    patams = params - learning_rate * params_grad

注意,上面的代码在每个epoch都对训练数据进行了打乱操作,这样可以保证不同epoch学习到的特征和训练样本的出现顺序没有关系。

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

小批量梯度下降结合了批量梯度下降和随机梯度下降的优点,它一次以小批量的训练数据计算目标函数的权重并更新参数。公式如下:

θ=θηθJ(θ;x(i:i+n);y(i:i+n))

其中,n为每批训练集的数量,一般设为50到256。
这个算法有下面几个方面的优点:
1. 相比较SGD增加了一次更新使用的训练数据量,使得目标函数收敛得更加平稳;
2. 可以使用矩阵操作对每批数据进行计算,大大提升了算法的效率。

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 gradient descent 虽然相较于批量梯度下降和随机梯度下降方法效果有所改善但是任然存在许多挑战:
1. 难以选择合适的学习速率:如果学习速率选择过小会造成网络收敛太慢,但是设得太大可能使得损失函数在最小点周围不断摇摆而永远达不到最小点;
2. 可以在训练开始时设置一个较大地学习率然后每训练若干个周期后按比例降低学习率,虽然这个方法有一些作用,但是由于降低学习率的周期是人为事先设定的,所以它不能很好地适应数据内在的规律;
3. 另一方面,我们对特征向量中的所有的特征都采用了相同的学习率,如果训练数据十分稀疏并且不同特征的变化频率差别很大,这时候对变化频率慢得特征采用大的学习率而对变化频率快的特征采用小的学习率是更好的选择。
4. 这些梯度下降方法难以逃脱”鞍点”, 如下图所示,鞍点既不是最大点也不是最小点,在这个点附近,所有方向上的梯度都接近于0,这些梯度下降算法很难逃离它。鞍点

梯度下降优化算法

下文我们将介绍常用的能够解决上述挑战的一些算法。

冲量(Momentum)

实际中,我们遇到的目标函数往往在不同的维度上梯度相差很大,比如在下面的函数等高线图中可以看出函数在纵向上要比横向陡峭得多。

然而SGD等基本梯度下降算法并不知道这些,因为y方向梯度大x方向梯度小所以它们会在y方向上不断摇摆而沿x方向缓慢移动,但是我们知道在y方向的震荡是无用的只有x方向的才在不断接近最优点。

冲量方法在SGD的基础上,加上了上一步的梯度:


其中γ通常设为0.9。

由于目标函数在y方向上摇摆,所以前后两次计算的梯度在y方向上相反,所以相加后相互抵消,而x方向上梯度方向不变,所以x方向的梯度是累加的,其效果就是损失函数在y方向上的震荡减小了,而更加迅速地从x方向接近最优点。

也可以把这个过程和在斜坡放一个球让其滚下类比:当从斜坡顶端释放一个小球时,由于重力的作用小球滚下的速度会越来越快;与此类似,冲量的作用会使相同方向的梯度不断累加,不同方向的梯度相互抵消,其效果就是逼近最优点的速度不断加快。

知乎上这篇文章解释得挺详细的。

Nesterov accelerated gradient

想象小球从山坡上滑落,它的速度沿着山坡不断加快,然而这并不是令我们满意的结果,当小球接近山谷(最优点)时,它已经有了很大的速度,很可能会再次冲向山谷的另一边,而错过了最优点。我们需要一颗更加“聪明”的小球,它能够感知坡度的变化,从而在它再次冲上山坡之前减速而避免错过山谷。

Nesterov accelerated gradient(NAG)就是一种让小球变“聪明”的方法。NAG不但增加了动量项,并且计算参数的梯度时,在损失函数中减去了梯度项将其作为下一次参数所在位置的预估:

同样,上式中的γ一般设为0.9。
如下图所示,蓝色的是动量方法的更新路径,首先计算一次梯度更新一小步,然后在下一次累加上一次计算的梯度从而更新一大步。而NAG算法每一步更新过程由两个步骤组成:第一步(γvt1, 图中棕色)使用之前计算的梯度移动一大步,第二步在移动后的位置计算的梯度方向移动一小步(图中红色线)进行修正,经过这样的两步合成了最终的绿线部分。

分析上面的原理可知,当“小球”将要冲上山坡的另一面时,红色线表示的预测梯度方向发生改变,从而将棕色向量往回拉达到了“减速”的效果。

通过NAG方法,我们使参数更新速率能够自适应“坡度”的变化,另一方面,我们希望每个单独的参数能够自适应各自的变化频率,比如,稀疏特征采用高的更新速率,其他特征采用相对较低的更新速率。下面介绍几种常用的方法。

Adagrad

Adagrad是一种适合处理稀疏特征的梯度更新算法,它对稀疏特征采用高的更新速率,而对其他特征采用相对较低的更新速率。Dean等人发现Adagrad能很好地提高SGD的鲁棒性,它已经被谷歌用来训练大规模的神经网络。

与之前我们使用相同的学习速率η来更新所有的参数不同,Adagrad对每个参数使用不同的参数进行更新。我们用gt,i来表示参数θi在第t次更新时的梯度,即

按照这个约定,SGD的更新规则可以写作:

$$\theta_{t+1,i}=\theta_{t,i}-\eta{g_{t,i}}$$

而Adagrad的更新规则可以表示为:

$$\theta_{t+1,i}=\theta_{t,i}-\frac{\eta}{\sqrt{G_{t,ii}+\epsilon}}g_{t,i}$$

其中,Gt,ii是一个Rd×d维的对角矩阵,其第i行第i列的元素为过去到当前第i个参数的梯度平方和,ϵ是为了防止分母为0的平滑项。进一步,可以将上式向量化如下:

$$\theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{G_t+\epsilon}}\bigodot{g_t}$$

其中,表示矩阵和向量的乘法。

这样,利用Adagrad就可以自动根据每个特征的稀疏性来设置不同的学习率。

Adagrad主要缺点是Gt累加了参数的历史梯度的平方,所以到后期学习率会越来越小,最后无法再学习到新的信息。下面介绍的算法就是来解决这个问题的。

Adadelta

Adadelta主要解决了Adagrad算法中学习率衰减过快的问题,它不再累加参数所有的历史梯度平方和,转而设定一个窗口w,只求前w个历史梯度平方的平均数E[g2]t,E[g2]t可以通过之前的梯度平方的平均和当前梯度的平方计算得到:

$$E[g^2]_t=\gamma{E[g^2]_{t-1}}+(1-\gamma)g_t^2$$

其中,γ相似于冲量参数γ.

Adadelta更新规则可以写作:

$$\Delta\theta_t=-\frac{\eta}{\sqrt{E[g^2]_t+\epsilon}}\bigodot{g_t}$$
或者
$$\Delta\theta_t=-\frac{\eta}{RMS[g]_t}\bigodot{g_t}$$

RMSprop

RMSprop由Hinton提出,实际上是Adadelta的一种特殊形式。

$$E[g^2]_t=0.9E[g^2]_{t-1}+0.1g_t^2\\\theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{E[g^2]_t}+\epsilon}\bigodot{g_t}$$

Adam

Adam的全称是Adaptive Moment Estimation, 它也是一种自适应学习率方法,与Adadelta和RMSprop类似,它将每个参数的历史梯度平方均值存于vt中,不同的是,Adam还使用了类似冲量的衰减项mt:

$$m_t=\beta_1{m_{t-1}}+(1-\beta_1)g_t\\v_t=\beta_2{v_{t-1}}+(1-\beta_2)g_t^2$$

mt,vt分别是梯度的带权平均和带权有偏方差,由于当β1,β2接近于1时,这两项接近于0,作者对他们进行了偏差修正:

m^t=mt1βt1v^t=vt1βt2

最终更新方程为:

θt+1=θtηv^t¯+ϵm^t

建议将β1设为0.9,β2设为0.999, ϵ设为108

效果

图a中,所有方法都从相同位置出发,经历不同的路径到达了最小点,其中Adagrad、Adadelta和RMSprop一开始就朝向正确的方向并且迅速收敛,而冲量、NAG则会冲向错误的方向,但是由于NAG会向前多“看”一步所以能很快找到正确的方向。

图b显示了这些方法逃离鞍点的能力,鞍点有部分方向有正梯度另一些方向有负梯度,SGD方法逃离能力最差,冲量和NAG方法也不尽如人意,而Adagrad、RMSprop、Adadelta很快就能从鞍点逃离出来。

0 0
原创粉丝点击