本文主要参考:
https://www.cnblogs.com/denny402/p/5074049.html 以及caffe官方文档
Solver的流程:
- 设计好需要优化的对象,以及用于学习的训练网络和用于评估的测试网络。(通过调用另外一个网络配置文件prototxt来进行)
- 通过forward和backward迭代的进行优化来跟新参数。
- 定期的评价测试网络。(可设定多少次训练后,进行一次测试)
- 在优化过程中显示模型和solver的状态
在每一次的迭代过程中,solver做了这几步工作:
- 调用forward算法来计算最终的输出值,以及对应的loss
- 调用backward算法来计算每层的梯度
- 根据选用的slover方法,利用梯度进行参数更新
- 记录并保存每次迭代的学习率、快照,以及对应的状态。
下面通过从上到下的分类说明来看看使用各中优化算法以及学习率计算方法的solver.prototxt配置方法:
1. 设置深度网络模型
- 训练网络和测试网络是一个网络:
net: "examples/mnist/lenet_train_test.prototxt"
- 训练和测试的网络不同,或者只需要训练的网络也可以只写train_net:
train_net: "examples/mnist/lenet_train.prototxt"
test_net: "examples/mnist/lenet_test.prototxt"
2. 设置测试网络的测试间隔(只在需要测试的时候需要)
- 设置测试完一次所有样本的迭代轮数test_iter:
t e s t _ i t e r = 测 试 样 本 数 量 测 试 层 b a t c h _ s i z e 大 小 test\_iter = \frac{测试样本数量}{测试层batch\_size大小} test_iter=测试层batch_size大小测试样本数量以及设置测试间隔test_interval(每训练多少次进行一次测试)
test_iter: 100
test_interval: 500
3. 设置学习率计算策略
对于所有的学习率计算策略都需要设置基础学习率以及最大迭代次数:
base_lr: 1e-2
max_iter: 20000
- fixed 学习率计算策略
该学习率计算策略保持base_lr不变,所以不需要其他参数:
lr_policy: "fixed"
- step 学习率计算策略
该学习率下更新base_lr的公式为:
当 前 学 习 率 = b a s e _ l r ∗ g a m m a f l o o r ( i t e r s t e p s i z e ) 当前学习率 = base\_lr * gamma^{floor(\frac{iter}{stepsize})} 当前学习率=base_lr∗gammafloor(stepsizeiter)其中iter为当前迭代次数,gamma, stepsize为需要设置的超参数
lr_policy: "step"
gamma: 0.1 # 学习速率变化因子
stepsize: 1000 # 每1000次迭代,降低学习速率
- multistep 学习率计算策略
step是均匀等间隔变化,而multistep则是根据stepvalue值变化,当迭代次数到了其中一个stepvalue,那么就根据下面的公式进行计算,在到达下一个stepvalue之前,其学习率维持不变
当 前 学 习 率 = b a s e _ l r ∗ g a m m a f l o o r ( i t e r s t e p v a l u e ) 当前学习率 = base\_lr * gamma^{floor(\frac{iter}{stepvalue})} 当前学习率=base_lr∗gammafloor(stepvalueiter)
lr_policy: "multistep"
gamma: 0.9
stepvalue: 5000
stepvalue: 7000
stepvalue: 8000
stepvalue: 9000
stepvalue: 9500
- poly 学习率计算策略
该学习率计算策略是进行多项式误差,更新公式为:
当 前 学 习 率 = b a s e _ l r ∗ ( 1 − ( i t e r m a x _ i t e r ) p o w e r ) 当前学习率 = base\_lr *(1 - {(\frac{iter}{max\_iter})}^{power}) 当前学习率=base_lr∗(1−(max_iteriter)power)
lr_policy: "poly"
power: 0.9
4.设置优化算法类型
caffe提供了六种优化算法来求解最优参数,在solver配置文件中,通过设置type类型来选择,各种优化算法之间的关系可以参考下面的图片
- SGD
caffe中默认的SGD优化算法是SGDM即SGD with momentum,所以配置方法为,此时 type: “SGD” 可以省略:
momentum: 0.9
type: "SGD"
- Nesterov
Nesterov优化算法是在SGDM的基础上结合未来的梯度信息来进行更新,没有引入新的超参数
momentum: 0.9
type: "Nesterov"
- AdaGrad
AdaGrad优化算法在SGD的基础上,根据自变量在每个维度上梯度值大小来调整各个维度上的学习率,只在二阶动量上进行累加,没有使用一阶动量,所以不需要超参数
type: "AdaGrad"
delta: 1e-6 #建议为1e-6,默认值为1e-8
- RMSProp
RMSProp优化方法在二阶动量上使用了EMA,caffe使用rms_decay来作为其超参数,而将momentum设为0.0
momentum: 0.0
type: "RMSProp"
rms_decay: 0.98
delta: 1e-6 #建议为1e-6,默认值为1e-8
- AdaDelta
AdaDelta是针对AdaGrad后期学习率过小找不到最优解的问题,与RMSProp一样在二阶动量中引入EMA,但同时引入一个状态变量Δx来代替基础学习率,所以其可以不需要设置base_lr,但caffe中通常可以将其设置为1.0
base_lr: 1.0
lr_policy: "fixed"
momentum: 0.95
delta: 1e-5 #建议为1e-5,默认值为1e-8
type: "AdaDelta"
- Adam
Adam优化方法在一阶动量以及二阶动量上均进行了EMA以及偏差修正,所以需要两个动量超参数值,并且由于Adam优化算法会自动调整学习率,所以我们设置基础学习率的调整策略为fixed:
# 下面是Adam作者建议的两个动量超参数取值
momentum: 0.9
momentum2: 0.999
lr_policy: "fixed"
type: "Adam"
delta = 1e-8 #默认值为1e-8
5. 设置权重衰减值以及正则化类型
weight_decay: 0.0005
regularization_type: "L2" # 默认是"L2",也可以设为"L1"
6. 其他常用参数
# 每间隔多少轮迭代在终端打印loss结果
display: 100
# Display the loss averaged over the last average_loss iterations
average_loss: 20
# accumulate gradients over `iter_size` * `batch_size` instances
iter_size = 64
# 每间隔多少轮迭代保存中间模型结果,一个权重结果caffemodel和一个用于恢复训练状态的solverstate
snapshot: 1000
# snapshot保存路径,其中最后的voc2012是保存的模型名字的开头部分
snapshot_prefix: "evaluation/snapshot/voc2012"
# 在GPU还是CPU下面运行
solver_mode: GPU # default = GPU
7.其他不常用参数
# 下面这种写法表示在不同的网络上进行测试
test_state: { stage: 'test-on-train' }
test_iter: 500
test_state: { stage: 'test-on-test' }
test_iter: 100
# test时是否计算loss,默认为false
test_compute_loss: true
# If true, run an initial test pass before the first iteration, ensuring
# memory availability and printing the starting value of the loss.
test_initialization: true
# Set clip_gradients to >= 0 to clip parameter gradients to that L2 norm,
# whenever their actual L2 norm is larger.
clip_gradients = -1 # default = -1
# whether to snapshot diff in the results or not. Snapshotting diff will help
# debugging but the final protocol buffer size will be much larger.
snapshot_diff: false # default = false
# snapshot的保存
snapshot_format: HDF5 # default = BINARYPROTO
# the device_id will that be used in GPU mode. Use device_id = 0 in default
device_id: 0 # default = 0
# If non-negative, the seed with which the Solver will initialize the Caffe
# random number generator -- useful for reproducible results. Otherwise,
# (and by default) initialize using a seed derived from the system clock.
random_seed: -1 # default = -1
# If true, print information about the state of the net that may help with
# debugging learning problems.
debug_info: true # default = false
# If false, don't save a snapshot after training finishes.
snapshot_after_train: true # default = true
# Overlap compute and communication for data parallel training
layer_wise_reduce: false # default = true
// Path to caffemodel file(s) with pretrained weights to initialize finetuning.
// Tha same as command line --weights parameter for caffe train command.
// If command line --weights parameter is specified, it has higher priority
// and overwrites this one(s).
// If --snapshot command line parameter is specified, this one(s) are ignored.
// If several model files are expected, they can be listed in a one
// weights parameter separated by ',' (like in a command string) or
// in repeated weights parameters separately.
weights: ','