solver算是caffe的核心的核心,它协调着整个模型的运作。caffe程序运行必带的一个参数就是solver配置文件。运行代码一般为:# caffe train --solver=*_slover.prototxt
在Deep Learning中,往往loss function是非凸的,没有解析解,我们需要通过优化方法来求解。solver的主要作用就是交替调用前向(forward)算法和后向(backward)算法来更新参数,从而最小化loss,实际上就是一种迭代的优化算法。
// The learning rate decay policy. The currently implemented learning rate
// policies are as follows:
// - fixed: always return base_lr.
// - step: return base_lr * gamma ^ (floor(iter / step))
// - exp: return base_lr * gamma ^ iter
// - inv: return base_lr * (1 + gamma * iter) ^ (- power)
// - multistep: similar to step but it allows non uniform steps defined by
// stepvalue
// - poly: the effective learning rate follows a polynomial decay, to be
// zero by the max_iter. return base_lr (1 - iter/max_iter) ^ (power)
// - sigmoid: the effective learning rate follows a sigmod decay
// return base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))
//
// where base_lr, max_iter, gamma, step, stepvalue and power are defined
// in the solver parameter protocol buffer, and iter is the current iteration.
optional string lr_policy = 8;
optional float gamma = 9; // The parameter to compute the learning rate.
optional float power = 10; // The parameter to compute the learning rate.
optional float base_lr = 5; // The base learning rate
// the stepsize for learning rate policy "step"
optional int32 stepsize = 13;
// the stepsize for learning rate policy "multistep"
repeated int32 stepvalue = 34;
使用最多的学习策略有fixed,step,inv,multistep
1、fixed 固定策略
故名思议就是学习率始终是一个固定值,如果是一个新手或者正准备训练一个全新的网络,建议使用这种策略。因为现在对于数据的分布和网络参数还都一无所知,fixed策略方便调节,我们可以根据训练情况包括loss和accuracy的值随时调节我们的学习率。比如,我喜欢开始时将学习率设置一个较大的值(0.1-0.01之间),但是不能使loss爆掉呦。而后通过观察loss和accuracy的值,比如两者下降缓慢或不在下降,出现震荡的情况,就将学习率调小。也就是逐次减小的策略。
2、step 均匀分步策略
这个策略要结合参数stepsize使用,当循环次数达到stepsize的整数倍时lr=base_lr*gamma^(floor(iter/stepsize)).在这里给大家说一个我最近使用这种策略所犯的错误。我从250000次开始继续训练我的网络,我将base_lr设置成0.001,stepsize设置成100000,gamma设置成0.1,我的本意是想让训练在300000次的时候学习率降到0.0001。结果呢?相信大家已经知道答案了学习率变成了1e-6.因此特别提醒你,如果你是在训练中途将学习策略改变成step,请仔细计算stepsize的值。
3、multistep 多分步或不均匀分步
这种学习策略也是我们最近才看到有人使用,这种学习策略和step策略很相似。这种学习策略需要配合参数stepvalue使用,stepvalue可以在文件中设置多个,如stepvalue=10000,stepvalue=20000,......,当迭代次数达到我们依次指定的stepvalue的值时,学习率就会根据公式重新计算。这种学习率策略我虽然尝试的并不多,但是我发现他有一个很好的用处,就是我们在刚开始训练网络时学习率一般设置较高,这样loss和accuracy下降很快,一般前200000次两者下降较快,后面可能就需要我们使用较小的学习率了。step策略由于过于平均,而loss和accuracy的下降率在整个训练过程中又是一个不平均的过程,因此有时不是很合适。fixed手工调节起来又很麻烦,这时multistep可能就会派上用场了。
base_lr: 0.01
momentum: 0.9 //上一次梯度更新的权重
weight_decay: 0.0005 //权重衰减项,防止过拟合的一个参数。
# The learning rate policy
lr_policy: "multistep"
gamma: 0.9
stepvalue: 5000
stepvalue: 7000
stepvalue: 8000
stepvalue: 9000
stepvalue: 9500
4、exp: 返回base_lr * gamma ^ iter, iter为当前迭代次数
5、poly: 学习率进行多项式误差, 返回 base_lr (1 - iter/max_iter) ^ (power)
6、sigmoid:习率进行sigmod衰减,返回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))
7、inv
其实,从公式中我们就可以看到,这种学习策略的优势就在于它使得学习率在每一次迭代时都减小,但每次减小又都是一个非常小的数,这样就省去的自己手动调节的麻烦。这种策略使用的也很普遍。
net: "examples/mnist/lenet_train_test.prototxt"
test_iter: 100
test_interval: 500
base_lr: 0.01
momentum: 0.9
type: SGD //这一行可以省掉,因为默认值就是SGD。
//六种选择
Stochastic Gradient Descent (type: "SGD"),
AdaDelta (type: "AdaDelta"),
Adaptive Gradient (type: "AdaGrad"),
Adam (type: "Adam"),
Nesterov’s Accelerated Gradient (type: "Nesterov") and
RMSprop (type: "RMSProp")
weight_decay: 0.0005
lr_policy: "inv"
gamma: 0.0001
power: 0.75
display: 100 //每训练100次,在屏幕上显示一次。如果设置为0,则不显示。
max_iter: 20000 //最大迭代次数。这个数设置太小,会导致没有收敛,精确度很低。设置太大,会导致震荡,浪费时间。
//快照。将训练出来的model和solver状态进行保存,snapshot用于设置训练多少次后进行保存,默认为0,不保存。snapshot_prefix设置保存路径。还可以设置snapshot_diff,是否保存梯度值,默认为false,不保存。也可以设置snapshot_format,保存的类型。有两种选择:HDF5 和BINARYPROTO ,默认为BINARYPROTO.
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
solver_mode: CPU //设置运行模式。默认为GPU,如果你没有GPU,则需要改成CPU,否则会出错。