【8】Caffe学习系列:solver优化方法(梯度下降算法)

对于神经网络模型,借助于BP算法可以高效地计算梯度,从而实施梯度下降算法。但梯度下降算法一个老大难的问题是:不能保证全局收敛。如果这个问题解决了,深度学习的世界会和谐很多。梯度下降算法针对凸优化问题原则上是可以收敛到全局最优的,因为此时只有唯一的局部最优点。而实际上深度学习模型是一个复杂的非线性结构,一般属于非凸问题,这意味着存在很多局部最优点(鞍点),采用梯度下降算法可能会陷入局部最优,这应该是最头疼的问题。这点和进化算法如遗传算法很类似,都无法保证收敛到全局最优。因此,我们注定在这个问题上成为“高级调参师”。可以看到,梯度下降算法中一个重要的参数是学习速率,适当的学习速率很重要:学习速率过小时收敛速度慢,而过大时导致训练震荡,而且可能会发散。理想的梯度下降算法要满足两点:收敛速度要快;能全局收敛。为了这个理想,出现了很多经典梯度下降算法的变种,下面将分别介绍它们。到目前为止,caffe提供了多种优化方法:

  • Stochastic Gradient Descent (type: "SGD"),
  • AdaDelta (type: "AdaDelta"),
  • Adaptive Gradient (type: "AdaGrad"),
  • Adam (type: "Adam"),
  • Nesterov’s Accelerated Gradient (type: "Nesterov"
  • RMSprop (type: "RMSProp")

Solver就是用来使loss最小化的优化方法。对于一个数据集D,需要优化的目标函数是整个数据集中所有数据loss的平均值。

其中,fW(x(i))计算的是数据x(i)上的loss, 先将每个单独的样本x的loss求出来,然后求和,最后求均值。 r(W)是正则项(weight_decay),为了减弱过拟合现象。

如果采用这种Loss 函数,迭代一次需要计算整个数据集,在数据集非常大的这情况下,这种方法的效率很低,这个也是我们熟知的梯度下降采用的方法。

根据计算目标函数L(W)采用数据量的不同,梯度下降算法又可以分为批量梯度下降算法(Batch Gradient Descent),即将所有训练数据看完一遍以后进行梯度更新,随机梯度下降算法(Stochastic GradientDescent),每个样本观察一次以后立即更新梯度和小批量梯度下降算法(Mini-batch Gradient Descent),它是前两种的折中形式。

对于批量梯度下降算法,其L(W)是在整个训练集上计算的,如果数据集比较大,可能会面临内存不足问题,而且其收敛速度一般比较慢。随机梯度下降算法是另外一个极端,L(W)是针对训练集中的一个训练样本计算的,又称为在线学习,即得到了一个样本,就可以执行一次参数更新。所以其收敛速度会快一些,但是有可能出现目标函数值震荡现象,因为高频率的参数更新导致了高方差。小批量梯度下降算法是折中方案,选取训练集中一个小批量样本计算L(W),这样可以保证训练过程更稳定,而且采用批量训练方法也可以利用矩阵计算的优势。这是目前最常用的梯度下降算法。


在实际中,通过将整个数据集分成几批(batches), 每一批就是一个mini-batch,其数量(batch_size)为N<<|D|,此时的loss 函数为:
 


有了loss函数后,就可以迭代的求解loss和梯度来优化这个问题。在神经网络中,用forward pass来求解loss,用backward pass来求解梯度。

在caffe中,默认采用的Stochastic Gradient Descent(SGD)进行优化求解,这是一种支持在线学习的梯度优化算法。后面几种方法也是基于梯度的优化方法(like SGD),因此本文只介绍一下SGD。其它的方法,有兴趣的同学,可以去看文献原文。

1、Stochastic gradient descent(SGD)

随机梯度下降(Stochastic gradient descent)是在梯度下降法(gradient descent)的基础上发展起来的,梯度下降法也叫最速下降法,具体原理在网易公开课《机器学习》中,吴恩达教授已经讲解得非常详细。SGD在通过负梯度和上一次的权重更新值Vt的线性组合来更新W,迭代公式如下:

 


 
其中,  是负梯度的学习率(base_lr),是上一次梯度值的权重(momentum),用来加权之前梯度方向对现在梯度下降方向的影响。这两个参数需要通过tuning来得到最好的结果,一般是根据经验设定的。如果你不知道如何设定这些参数,可以参考相关的论文。

在深度学习中使用SGD,比较好的初始化参数的策略是把学习率设为0.01左右(base_lr: 0.01),在训练的过程中,如果loss开始出现稳定水平时,对学习率乘以一个常数因子(gamma),这样的过程重复多次。

对于momentum,一般取值在0.5--0.99之间。通常设为0.9,momentum可以让使用SGD的深度学习方法更加稳定以及快速。

momentum的原理解释:

0?wx_fmt=png

可以看到,参数更新时不仅考虑当前梯度值,而且加上了一个积累项(冲量),但多了一个超参0?wx_fmt=png,一般取接近1的值如0.9。相比原始梯度下降算法,冲量梯度下降算法有助于加速收敛。当梯度与冲量方向一致时,冲量项会增加,而相反时,冲量项减少,因此冲量梯度下降算法可以减少训练的震荡过程。

换句话说,当本次梯度下降方向与上次更新量的方向相同时,上次的更新量能够对本次的搜索起到一个正向加速的作用。当本次梯度下降方向与上次更新量的方向相反时,上次的更新量能够对本次的搜索起到一个减速的作用。既减少震荡,又大方向不变(本次梯度下降方向),从而保证了效率和正确的收敛。

关于更多的momentum,请参看Hinton的《A Practical Guide to Training Restricted Boltzmann Machines》。  

实例: 

base_lr: 0.01 
lr_policy: "step"
gamma: 0.1   
stepsize: 1000  
max_iter: 3500 
momentum: 0.9

lr_policy设置为step,则学习率的变化规则为 base_lr * gamma ^ (floor(iter / stepsize))

即前1000次迭代,学习率为0.01;初始的1000次(取决于stepsize指定),采用base_lr.

第1001-2000次迭代,学习率为0.001; lr =  base_lr * gamma ^ (floor(iter / stepsize))=0.01*0.1^(floor(iter/1000))=0.001,floor为向下取整,那么floor(iter/1000)一直是1,其中iter∈(1001,2000).

第2001-3000次迭代,学习率为0.0001,lr =  base_lr * gamma ^ (floor(iter / stepsize))=0.01*0.1^(floor(iter/1000))=0.01*0.1^2=0.0001,其中iter∈(2001,3000)

第3001-3500次迭代,学习率为1e10-5 ,lr =  base_lr * gamma ^ (floor(iter / stepsize))=0.01*0.1^(floor(iter/1000))=0.01*0.1^3=0.00001,其中iter∈(3001,3500)

下图是来自于官网的一段介绍:

上面的设置只能作为一种指导,它们不能保证在任何情况下都能得到最佳的结果,有时候这种方法甚至不work。如果学习的时候出现diverge(比如,你一开始就发现非常大或者NaN或者inf的loss值或者输出),此时你需要降低base_lr的值(比如,0.001),然后重新训练,这样的过程重复几次直到你找到可以work的base_lr。

2、AdaDelta

AdaDelta是一种”鲁棒的学习率方法“,是基于梯度的优化方法(like SGD)。

具体的介绍文献:

M. Zeiler ADADELTA: AN ADAPTIVE LEARNING RATE METHODarXiv preprint, 2012.

示例:

net: "examples/mnist/lenet_train_test.prototxt"
test_iter: 100
test_interval: 500
base_lr: 1.0
lr_policy: "fixed"
momentum: 0.95
weight_decay: 0.0005
display: 100
max_iter: 10000
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet_adadelta"
solver_mode: GPU
type: "AdaDelta"
delta: 1e-6

从最后两行可看出,设置solver type为Adadelta时,需要设置delta的值。

3、AdaGrad

AdaGrad(adaptive gradient)是Duchi在2011年提出的一种学习速率自适应的梯度下降算法。在训练迭代过程,其学习速率是逐渐衰减的,经常更新的参数其学习速率衰减更快,这是一种自适应算法。

0?wx_fmt=png

其中是梯度平方的积累量,在进行参数更新时,学习速率要除以这个积累量的平方根,其中加上一个很小值是为了防止除0的出现。由于是该项逐渐增加的,那么学习速率是衰减的。考虑如图2所示的情况,目标函数在两个方向的坡度不一样,如果是原始的梯度下降算法,在接近坡底时收敛速度比较慢。而当采用AdaGrad,这种情况可以被改观。由于比较陡的方向梯度比较大,其学习速率将衰减得更快,这有利于参数沿着更接近坡底的方向移动,从而加速收敛。(下图是AdaGrad的示意图)

0?wx_fmt=png

具体的介绍文献:

Duchi, E. Hazan, and Y. Singer. Adaptive Subgradient Methods for Online Learning and Stochastic OptimizationThe Journal of Machine Learning Research, 2011.

示例:

net: "examples/mnist/mnist_autoencoder.prototxt"
test_state: { stage: 'test-on-train' }
test_iter: 500
test_state: { stage: 'test-on-test' }
test_iter: 100
test_interval: 500
test_compute_loss: true
base_lr: 0.01
lr_policy: "fixed"
display: 100
max_iter: 65000
weight_decay: 0.0005
snapshot: 10000
snapshot_prefix: "examples/mnist/mnist_autoencoder_adagrad_train"
# solver mode: CPU or GPU
solver_mode: GPU
type: "AdaGrad"

4、Adam

Adam全称Adaptive moment estimation,是Kingma等在2015年提出的一种新的优化算法,其结合了Momentum和RMSprop算法的思想。相比Momentum算法,其学习速率是自适应的,而相比RMSprop,其增加了冲量项。所以,Adam是两者的结合体:

0?wx_fmt=png

可以看到前两项和Momentum和RMSprop是非常一致的,由于和的初始值一般设置为0,在训练初期其可能较小,第三和第四项主要是为了放大它们。最后一项是参数更新。其中超参数的建议值是0?wx_fmt=png

 具体的介绍文献:

D. Kingma, J. Ba. Adam: A Method for Stochastic OptimizationInternational Conference for Learning Representations, 2015.

5、NAG

NAG算法全称Nesterov Accelerated Gradient,是YuriiNesterov在1983年提出的对冲量梯度下降算法的改进版本,作为凸优化中最理想的方法,其速度更快。其变化之处在于计算“超前梯度”更新冲量项,具体公式如下:

0?wx_fmt=png

既然参数要沿着0?wx_fmt=png更新,不妨计算未来位置0?wx_fmt=png的梯度,然后合并两项作为最终的更新项,其具体效果如图1所示,可以看到一定的加速效果。

0?wx_fmt=png

 具体的介绍文献:

 I. Sutskever, J. Martens, G. Dahl, and G. Hinton. On the Importance of Initialization and Momentum in Deep LearningProceedings of the 30th International Conference on Machine Learning, 2013.

示例:

net: "examples/mnist/mnist_autoencoder.prototxt"
test_state: { stage: 'test-on-train' }
test_iter: 500
test_state: { stage: 'test-on-test' }
test_iter: 100
test_interval: 500
test_compute_loss: true
base_lr: 0.01
lr_policy: "step"
gamma: 0.1
stepsize: 10000
display: 100
max_iter: 65000
weight_decay: 0.0005
snapshot: 10000
snapshot_prefix: "examples/mnist/mnist_autoencoder_nesterov_train"
momentum: 0.95
# solver mode: CPU or GPU
solver_mode: GPU
type: "Nesterov"

6、RMSprop

RMSprop是Hinton在一次 Coursera课程上讲到的,其算是对Adagrad算法的改进,主要是解决学习速率过快衰减的问题。其实思路很简单,类似Momentum思想,引入一个超参数,在积累梯度平方项进行衰减:

0?wx_fmt=png

可以认为仅仅对距离时间较近的梯度进行积累,其中一般取值0.9,其实这样就是一个指数衰减的均值项,减少了出现的爆炸情况,因此有助于避免学习速率很快下降的问题。同时Hinton也建议学习速率设置为0.001。RMSprop是属于一种比较好的优化算法了。

具体的介绍文献:

T. Tieleman, and G. Hinton. RMSProp: Divide the gradient by a running average of its recent magnitudeCOURSERA: Neural Networks for Machine Learning.Technical report, 2012.

 示例:

net: "examples/mnist/lenet_train_test.prototxt"
test_iter: 100
test_interval: 500
base_lr: 1.0
lr_policy: "fixed"
momentum: 0.95
weight_decay: 0.0005
display: 100
max_iter: 10000
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet_adadelta"
solver_mode: GPU
type: "RMSProp"
rms_decay: 0.98

最后两行,需要设置rms_decay值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值