caffe:train_val.prototxt,solver.prototxt,deploy.prototxt

caffe中train_val.prototxt和deploy.prototxt文件的区别

以LeNet网络结构为例子,这两个文件不同点主要在一前一后,中间是相同的

train_val.prototxt 中的开头

里面定义的是训练和验证时候的网络,所以在开始的时候要定义训练集和验证集的来源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
# 这里定义了之前将数据集转成lmdb数据格式的文件位置
source: "examples/mnist/mnist_train_lmdb"
# 这个定义了一次行送入网络的图像个数
batch_size: 64
backend: LMDB
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
# 这里定义了验证集的数据来源
source: "examples/mnist/mnist_test_lmdb"
batch_size: 100
backend: LMDB
}
}

deploy.prototxt 中的开头

这个配置文件适用于部署,也就是用于实际场景时候的配置文件,所以开始的时候不必在定义数据集的来源,但是需要定义输入数据的大小格式

1
2
3
4
5
6
7
8
name: "LeNet"
layer {
name: "data"
type: "Input"
top: "data"
# 输入数据的batch size, channel, width, height
input_param { shape: { dim: 64 dim: 1 dim: 28 dim: 28 } }
}

train_val.prototxt 中的结尾

如果是一般的卷积网络的话,最后面都是用一个全连接,将feature map 转成固定长度的向量,然后输出种类的个数。所以在最后的时候,需要说明输出种类的个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
# 在这里定义了输出种类的个数
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}

因为这里面包含了验证的部分,验证的时候,需要输出结果的准确率,所以需要定义准确率的输出

1
2
3
4
5
6
7
8
9
10
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}

最后还有一个不同就是,因为是训练模型,所以包括forward和backward,所以最后需要定义一个损失函数。这里用的是SoftmaxWithLoss,而在deploy.prototxt,因为只有forward,所以定义的是Softmax,也就是分类器

1
2
3
4
5
6
7
8
layer {
name: "loss"
# 定义的是损失函数
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}

deploy.prototxt 中的最后

这里定义了Softmax分类器,输出最后各类的概率值

1
2
3
4
5
6
7
layer {
name: "prob"
# 定义的是分类器
type: "Softmax"
bottom: "ip2"
top: "prob"
}

train_val.prototxt 和 deploy.prototxt中间部分

两个的中间部分都是一样的,定义了一些卷积、激活、池化、Dropout、LRN(local response normalization)、全连接等操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
... ...

solver.prototxt配置文件参数设置及含义

首先明确solver.prototxt的参数的含义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
net: "examples/myproject/train_val.prototxt"   #训练或者测试配置文件
test_iter: 40 #完成一次测试需要的迭代次数
test_interval: 475 #测试间隔:每个epoch包含的iteration数量
base_lr: 0.01 #基础学习率
lr_policy: "step" #学习率变化规律
gamma: 0.1 #学习率变化指数
stepsize: 9500 #学习率变化频率
display: 20 #屏幕显示间隔
max_iter: 47500 #最大迭代次数
momentum: 0.9 #动量
weight_decay: 0.0005 #权重衰减
snapshot: 5000 #保存模型间隔
snapshot_prefix: "models/A1/caffenet_train" #保存模型的前缀
solver_mode: CPU #使用CPU还是GPU

这里面需要注意的就是test_iter,max_iter,test_interval,和stepsize四个参数。接下来我们做下简单地分析。

  • test_iter: 表示完成一epoch测试需要的迭代次数;比如,你的test阶段的batchsize=25,而你的测试数据为1000张图片,则测试时一个epoch中有1000/25=40个iteration
  • test_interval:测试间隔:每个epoch包含的iteration数量;比如训练样本一共121368个样本,而我们训练的时候batchsize=256,可以得知一个epoch需要121368/256=475 次迭代才能完成,所以这里将test_interval设置为475,意为每训练一个epoch就进行测试。
  • max_iter: 网络的最大迭代次数;如果想训练100个epoch,则最大迭代次数max_iter设置为47500。
  • stepsize:学习率变化规律;我们设置该参数为随着迭代次数的增加,慢慢变低。总共迭代47500次(100个epoch),若我们想变化5次的话,stepsize设置为47500/5=9500,即每迭代9500次,我们就降低一次学习率。