caffe学习(8)Solver 配置详解

http://yanjoy.win/2016/11/08/caffe%E5%AD%A6%E4%B9%A0%EF%BC%888%EF%BC%89Solver%20%E9%85%8D%E7%BD%AE%E8%AF%A6%E8%A7%A3/

Solver是求解学习模型的核心配置文件,网络确定后,solver就决定了学习的效果。本文结合caffe.proto和网上资料,对solver配置进行学习。

Solver
Caffe学习系列(7):solver及其配置,denny402


Solver在caffe中的定义

通常的solver文件与net文件相互关联,同样的net我们往往使用不同的solver尝试得到最好的效果,其运行代码为:

caffe train --solver=*_slover.prototxt

关于solver的一切,都在caffe.proto文件中message SolverParameter 这一部分。

网络文件源

1
2
3
4
5
6
7
8
9
10
// Proto filename for the train net, possibly combined with one or more
// test nets.
optional string net = 24;
// Inline train net param, possibly combined with one or more test nets.
optional NetParameter net_param = 25;
 
optional string train_net = 1; // Proto filename for the train net.
repeated string test_net = 2; // Proto filenames for the test nets.
optional NetParameter train_net_param = 21; // Inline train net params.
repeated NetParameter test_net_param = 22; // Inline test net params.

 

这是最开始的部分,需要说明net文件的位置。在这四个train_net_param, train_net, net_param, net字段中至少需要出现一个,当出现多个时,就会按着(1) test_net_param, (2) test_net, (3) net_param/net 的顺序依次求解。必须为每个test_net指定一个test_iter。还可以为每个test_net指定test_level和/或test_stage。注意的是:文件的路径要从caffe的根目录开始,其它的所有配置都是这样。
可以看到这几行的标签序号并不是顺序的,也说明caffe在不断地修改,下一个可用的序号是41。

网络状态

1
2
3
4
5
6
7
8
9
// The states for the train/test nets. Must be unspecified or
// specified once per net.
//
// By default, all states will have solver = true;
// train_state will have phase = TRAIN,
// and all test_state's will have phase = TEST.
// Other defaults are set according to the NetState defaults.
optional NetState train_state = 26;
repeated NetState test_state = 27;

 

网络状态必须是未指定的或者只能在一个网络中指定一次。
关于NetState,其定义为:

1
2
3
4
5
6
7
8
9
message NetState {
optional Phase phase = 1 [default = TEST];
optional int32 level = 2 [default = 0];
repeated string stage = 3;
}
enum Phase {
TRAIN = 0;
TEST = 1;
}

 

迭代器

1
2
// The number of iterations for each test net.
repeated int32 test_iter = 3;

 

首先是test_iter,这需要与test layer中的batch_size结合起来理解。mnist数据中测试样本总数为10000,一次性执行全部数据效率很低,因此我们将测试数据分成几个批次来执行,每个批次的数量就是batch_size。假设我们设置batch_size为100,则需要迭代100次才能将10000个数据全部执行完。因此test_iter设置为100。执行完一次全部数据,称之为一个epoch。

1
2
3
4
5
6
// The number of iterations between two testing phases.
optional int32 test_interval = 4 [default = 0];
optional bool test_compute_loss = 19 [default = false];
// If true, run an initial test pass before the first iteration,
// ensuring memory availability and printing the starting value of the loss.
optional bool test_initialization = 32 [default = true];

 

test_interval是指测试间隔,每训练test_interval次,进行一次测试。同时test_compute_loss可以选择是否计算loss。test_initialization是指在第一次迭代前,计算初始的loss以确保内存可用。

1
2
3
4
5
6
7
8
9
optional float base_lr = 5; // The base learning rate
// the number of iterations between displaying info. If display = 0, no info
// will be displayed.
optional int32 display = 6;
// Display the loss averaged over the last average_loss iterations
optional int32 average_loss = 33 [default = 1];
optional int32 max_iter = 7; // the maximum number of iterations
// accumulate gradients over `iter_size` x `batch_size` instances
optional int32 iter_size = 36 [default = 1];

base_lr指基础的学习率;display是信息显示间隔,迭代一定次数显示一次信息。average_loss用于显示在上次average_loss迭代中的平均损失。max_iter是最大迭代次数,需要合适设置达到精度、震荡的平衡。iter_size是迭代器大小,梯度的计算是通过iter_size x batch_size决定的。

学习策略

1
2
3
4
5
6
7
8
9
10
11
12
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 momentum = 11; // The momentum value.
optional float weight_decay = 12; // The weight decay.
// regularization types supported: L1 and L2
// controlled by weight_decay
optional string regularization_type = 29 [default = "L2"];
// the stepsize for learning rate policy "step"
optional int32 stepsize = 13;
// the stepsize for learning rate policy "multistep"
repeated int32 stepvalue = 34;

只要是梯度下降法来求解优化,都会有一个学习率,也叫步长。base_lr用于设置基础学习率,在迭代的过程中,可以对基础学习率进行调整。怎么样进行调整,就是调整的策略,由lr_policy来设置。caffe提供了多种policy:

  • fixed: 总是返回base_lr(学习率不变)
  • step: 返回 base_lr * gamma ^ (floor(iter / step))
    还需要设置stepsize参数以确定step,iter表示当前迭代次数。
  • exp: 返回base_lr * gamma ^ iter, iter为当前迭代次数
  • inv: 如果设置为inv,还需要设置一个power, 返回base_lr (1 + gamma iter) ^ (- power)
  • multistep: 如果设置为multistep,则还需要设置一个stepvalue。这个参数和step很相似,step是均匀等间隔变化,而multistep则是根据stepvalue值变化。
  • poly: 学习率进行多项式误差, 返回 base_lr (1 - iter/max_iter) ^ (power)
  • sigmoid: 学习率进行sigmod衰减,返回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))。

multistep示例:

1
2
3
4
5
6
7
8
9
10
11
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

 

之后有momentum,上次梯度更新的权重;weight_decay权重衰减,防止过拟合;regularization_type正则化方式。

clip_gradients

1
optional float clip_gradients = 35 [default = -1];

 

参数梯度的实际L2范数较大时,将clip_gradients设置为> = 0,以将参数梯度剪切到该L2范数。具体作用还不是很理解。

snapshot快照

1
2
3
4
5
6
7
8
9
10
optional int32 snapshot = 14 [default = 0]; // The snapshot interval
optional string snapshot_prefix = 15; // The prefix for the snapshot.
// whether to snapshot diff in the results or not. Snapshotting diff will help
// debugging but the final protocol buffer size will be much larger.
optional bool snapshot_diff = 16 [default = false];
enum SnapshotFormat {
HDF5 = 0;
BINARYPROTO = 1;
}
optional SnapshotFormat snapshot_format = 37 [default = BINARYPROTO];

 

快照可以将训练出来的model和solver状态进行保存,snapshot用于设置训练多少次后进行保存,默认为0,不保存。snapshot_prefix设置保存路径。还可以设置snapshot_diff,是否保存梯度值,保存有利于调试,但需要较大空间存储,默认为false,不保存。也可以设置snapshot_format,保存的类型。有两种选择:HDF5 和BINARYPROTO ,默认为BINARYPROTO。

运行模式

1
2
3
4
5
6
7
8
9
10
11
enum SolverMode {
CPU = 0;
GPU = 1;
}
optional SolverMode solver_mode = 17 [default = GPU];
// the device_id will that be used in GPU mode. Use device_id = 0 in default.
optional int32 device_id = 18 [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.
optional int64 random_seed = 20 [default = -1];

设置CPU或GPU模式,在GPU下还可以指定使用哪一块GPU运行。random_seed用于初始生成随机数种子。

Solver类型

1
2
3
4
5
6
7
8
9
10
11
// type of the solver
optional string type = 40 [default = "SGD"];
 
// numerical stability for RMSProp, AdaGrad and AdaDelta and Adam
optional float delta = 31 [default = 1e-8];
// parameters for the Adam solver
optional float momentum2 = 39 [default = 0.999];
 
// RMSProp decay value
// MeanSquare(t) = rms_decay*MeanSquare(t-1) + (1-rms_decay)*SquareGradient(t)
optional float rms_decay = 38;

type是solver的类型,目前有SGD、NESTEROV、ADAGRAD、RMSPROP、ADADELTA、ADAM = 5这六类。之后的一些是这些类型的特有参数,根据需要设置。

杂项

1
2
3
4
5
6
// If true, print information about the state of the net that may help with
// debugging learning problems.
optional bool debug_info = 23 [default = false];
 
// If false, don't save a snapshot after training finishes.
optional bool snapshot_after_train = 28 [default = true];

debug_info用于输出调试信息。snapshot_after_train用于训练后是否输出快照。

posted on 2017-10-17 20:08  塔上的樹  阅读(387)  评论(0)    收藏  举报