Caffe中Solver方法(HGL)

Solver就是用来使loss最小化的优化方法,loss是损失函数。损失函数最小的目标就是求解全局最小值。

假设有数据集(X1, X2, …, Xn),对应的(y1, y2, …, yn),其中每个Xi对应m个元素。loss函数定义为

其中,F(X)为模型。假设F(X)为线性函数:

, x0 = 1

目标:min Φ(θ),loss函数最小。估计最优系数(θ0, θ1, θ2, …, θm)。

预备知识:梯度下降法(最速下降法)

顾名思义,梯度下降法的计算过程就是沿梯度下降的方向求解极小值。

具体过程如下(如图1所示):

  1. 首先对θ赋值,这个值可以是随机的,也可以让θ是一个全零的向量(初值的选择非常影响梯度下降算法的好与坏)。
  2. 改变θ的值,使得Φ(θ)按梯度下降的方向进行减少。

图1 梯度下降描述(来自于斯坦福大学,《机器学习》公开课[2])

????过程2)可以表示为:

????????

????????其中α为步长。

由于我们每进行一次参数更新需要计算整体训练数据的梯度,批量梯度下降会变得很慢,并且会遇到内存吃不下数据就挂了。同时批量梯度下降也无法支持模型的在线更新,例如,新的样本不停的到来。

1. SGD (随机梯度下降算法,Stochastic gradient descent)

在梯度下降中,对于θ的更新,所有的样本都有贡献,也就是参与调整θ,其计算得到的是一个标准梯度。如果数据量非常大,那么运算速度很慢。而随机梯度下降算法的随机也就是说我用样本中的一个例子来近似我所有的样本,来调整θ。这样速度更快,但是更容易陷入局部极小。随机梯度下降算法可以表示为:

????

/*****************[1] *****************/

Caffe中的SGD在通过负梯度和上一次的权重更新值Vt的线性组合来更新θ,迭代公式如下:

????

????

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

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

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

关于更多的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; 第1001-2000次迭代,学习率为0.001; 第2001-3000次迭代,学习率为0.00001,第3001-3500次迭代,学习率为10-5

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

/*****************[1] *****************/

2. AdaGrad(自适应梯度,Adaptive Gradient)

自适应梯度与SGD类似,AdaGrad的更新速率是可变的。更新速率一定,不一定适合所有的更新阶段。所以AdaGrad调整的是Gradient,对于所有的参数,随着更新的总距离增多,学习速度随之变缓。可以表示为:

????

????其中(θi)tt步的参数,ε很小,保证非0。

缺点:学习率单调递减,训练后期学习率非常小;需要手动设置全局学习率;更新
θt时,左右两边单位不统一。

参考文献:Duchi, E. Hazan, and Y. Singer.?Adaptive Subgradient Methods for Online Learning and Stochastic Optimization

/*****************[1] *****************/

示例:


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"

/*****************[1] *****************/

3. AdaDelta

AdaDelta基本思想是用一阶的方法,近似模拟二阶牛顿法,是对AdaGrad的缺点进行改进。可表示为:

????

缺点:类似于AdaGrad,其学习率是单调递减的,训练后期学习率非常小。

/*****************[1] *****************/

示例:


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

/*****************[1] *****************/

4. RMSprop

RMSprop和Adadelta是在差不多的时间各自独立产生的工作,目的都是为了缓解Adagrad的学习速率减少的问题。实际上RMSprop和我们在Adadelta中推到的第一个更新向量是相同的:

????

????

其中,ρ建议取0.9,α建议取0.001。

/*****************[1] *****************/

示例:


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

/*****************[1] *****************/

5. NAG

这个算法严格的说来是凸优化中的算法,具有O(1/t^2)的收敛率,收敛速度比较快。因为 DNN是一个non-convex的model,所以NAG方法并不能达到这个收敛速度。caffe文档中指出,这个方法对于某些deeplearning 的 architecture是非常有效的。与SGD类似,具体更新过程如下:

????

????

通过调节αμ可以有效的改变迭代速度以及迭代的方向。可以看出θi的更新是和上次增量以及梯度线性相关的。在Caffe的文档中给出了一个基本的调参规则[3]:

a. 初始的learning rate建议设置为0.01。

b. 在迭代过程中当loss到达了一个明显的"plateau"的时候,则以10倍的速度drop learning rate,相当于稍微减少步长,

c. μ是一个调解参数,一般设置为0.9,这个参数起到一个平滑的作用,可以让SGD算法更加稳定和快速

d. μα是一个反相关的,增加μ,则降低α,反之亦然。

/*****************[1] *****************/

示例:


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"

/*****************[1] *****************/

6. Adam(个人认为一般都合适的caffe的solver方法)

Adaptive Moment Estimation(Adam) 也是一种不同参数自适应不同学习速率方法,与Adadelta与RMSprop区别在于,它计算历史梯度衰减方式不同,不使用历史平方衰减,其衰减方式类似动量,如下[4]:

????

????

WtVt分别是梯度的带权平均和带权有偏方差,初始为0向量,Adam的作者发现他们倾向于0向量(接近于0向量),特别是在衰减因子(衰减率)ρ1,ρ2接近于1时。为了改进这个问题,对WtVt进行偏差修正(bias-corrected):

????

????

最终,Adam的更新方程为:

????

[1] http://www.cnblogs.com/denny402/

[2] http://open.163.com/movie/2008/1/M/C/M6SGF6VB4_M6SGHFBMC.html

[3] http://blog.sina.com.cn/s/blog_eb3aea990102v41r.html

[4] http://blog.csdn.net/heyongluoyao8/article/details/52478715?locationNum=7

时间: 2024-11-10 10:50:09

Caffe中Solver方法(HGL)的相关文章

Caffe中的优化方法

在Deep Learning中,往往loss function是非凸的,没有解析解,我们需要通过优化方法来求解.Caffe通过协调的进行整个网络的前向传播推倒以及后向梯度对参数进行更新,试图减小损失. Caffe已经封装好了三种优化方法,分别是Stochastic Gradient Descent (SGD), AdaptiveGradient (ADAGRAD), and Nesterov's Accelerated Gradient (NAG). Solver的流程: 1.     设计好需

Caffe源代码中Solver文件分析

Caffe源代码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/solver.hpp文件的内容: 1.      include文件: <caffe/solver.hpp>:此文件的介绍能够參考: http://blog.csdn.net/fengbingchun/article/details/62423060 2.      模板类Solver:虚基类 3.      模板类Wo

caffe中权值初始化方法

首先说明:在caffe/include/caffe中的 filer.hpp文件中有它的源文件,如果想看,可以看看哦,反正我是不想看,代码细节吧,现在不想知道太多,有个宏观的idea就可以啦,如果想看代码的具体的话,可以看:http://blog.csdn.net/xizero00/article/details/50921692,写的还是很不错的(不过有的地方的备注不对,不知道改过来了没). 文件 filler.hpp提供了7种权值初始化的方法,分别为:常量初始化(constant).高斯分布初

Caffe中对MNIST执行train操作执行流程解析

之前在 http://blog.csdn.net/fengbingchun/article/details/49849225 中简单介绍过使用Caffe train MNIST的文章,当时只是仿照caffe中的example实现了下,下面说一下执行流程,并精简代码到仅有10余行: 1.        先注册所有层,执行layer_factory.hpp中类LayerRegisterer的构造函数,类LayerRegistry的AddCreator和Registry静态函数:关于Caffe中Lay

CAFFE中训练与使用阶段网络设计的不同

神经网络中,我们通过最小化神经网络来训练网络,所以在训练时最后一层是损失函数层(LOSS), 在测试时我们通过准确率来评价该网络的优劣,因此最后一层是准确率层(ACCURACY). 但是当我们真正要使用训练好的数据时,我们需要的是网络给我们输入结果,对于分类问题,我们需要获得分类结果,如下右图最后一层我们得到 的是概率,我们不需要训练及测试阶段的LOSS,ACCURACY层了. 下图是能过$CAFFE_ROOT/python/draw_net.py绘制$CAFFE_ROOT/models/caf

Caffe 中添加自己的网络层

写在前面: Caffe 中有众多的网络层,最新版本的代码已经涵盖了很多种类型的网络层,然而,有时候由于各种原因,其给定的网络层不能满足我们的要求,这时候就要对其更改,以使其满足自己的需求,感谢作者开源代码以及众多的代码维护者. 由于Caffe 中的网络层都是直接或者间接地给予Layer 基类,所以,在我们需要添加新的类型时,就需要选择好自己的基类,以使我们能够更好的利用基类已有的一些方法.我们新建的类可以基于 1. 直接继承于Layer 2. 继承于DataLayer 3. 继承于NeuronL

如何在caffe中添加新的Layer

如何在caffe中添加新的Layer 本文分为两部分,先写一个入门的教程,然后再给出自己添加maxout与NIN的layer的方法 (一) 其实在Github上已经有答案了(https://github.com/BVLC/caffe/issues/684) Here's roughly the process I follow. Add a class declaration for your layer to the appropriate one of common_layers.hpp, 

SSH配置环境都正常,但是每次执行到Action中的方法时就中断了,而且不报任何错误

SSH配置环境都正常,但是每次执行到Action中的方法时就不执行课,而且不报任何错误.Action中的方法封装的是业务层,业务层封装DAO层,检查了一天才发现错误在哪. 在applicationContext.xml中报了一个异常,如: Multiple annotations found at this line: - Exception 'com/dao/StudentDAO : Unsupported major.minor version 51.0' - Exception 'com/

Java中的方法重写 与 final关键字

Java中的方法重写 与 final关键字 以下程序是否存在错误? class Base { private final void method() { System.out.println("In Base..."); } } class Sub extends Base { public void method() { System.out.println("In Sub..."); } } 答案 正确的. 使用final关键字可以声明类.成员变量和成员方法,一