caffe-数据&模型-模型

模型三部分参数

模型是caffe学习系统包含数据与模型两个核心组件之一。一个caffe模型含有三部分参数:

  • 要学习的参数:

即权值,通过 初始化和反向传播得到更新。随着训练的结束,要学习的参数就此确定,也意味着确定了一个具体的模型。这个模型或者说是最终的学习参数会保存在.caffemodel文件中。我们可以直接使用这个模型,或者是在这个模型的基础上继续学习。

  • 网络结构超参数:

就是Net的蓝图,即如何构建一个具体的Net,是一种构建策略。比如当前卷积层的kernel数量,kernel大小,步长等参数,显然,结构参数是在训练网络前就确定了的。注意:同一个Net的训练结构和测试结构可能不同。结构参数由Net的蓝图文件.prototxt提供,读取这个文件,得到Net的结构细节,从而指导caffe构建制定Net。

  • 训练超参数:

控用于制训练过程的参数,如learning rate,迭代次数,CPU或GPU训练,等。其描述存在于一个.prototxt文件,一般使用solver.prototxt这个文件名。

先准备数据。在将原始数据(raw data)转换为LMDB格式之后,就可以由数据层(DataLayer)不断从LMDB(磁盘上)读取数据进入网络。

为了对caffe的pipline有个清晰的理解,在工作目录创建文件夹my_linearReggresion 存放关于这个网络的所有内容,将之前创建好的LMDB数据文件放入 my_linearReggresion。之后创建网络结构文件 mylr.prototxt 和训练超参数文件 lr_solver.prototxt

此时的my_linearReggresion目录tree如下:

1
2
3
4
5
6
7
8
9
.
├── lr_solver.prototxt
├── mnist_test_lmdb
│   ├── data.mdb
│   └── lock.mdb
├── mnist_train_lmdb
│   ├── data.mdb
│   └── lock.mdb
└── mylr.prototxt

上述是以一个简单的logistic reggresion为例。其网络结构如下图(包含训练和测试两个结构,两者共同的层只需定义一遍,不同阶段的要分别定义):
[插图结构图]
参照结构图,定义网络结构超参数文件和训练超参数文件。

编辑mylr.prototxt

先编辑网络结构超参数文件,就是编辑mylr.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
name: "lrNet"
# 数据层,用于train
layer{
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param{
scale: 0.0039063
}
data_param{
source: "MNIST_LMDB_PATH/mnist_train_lmdb"
batch_size: 64
backend: lmdb
}
}
# 数据层,用于test
layer{
name: "mnist"
type: "Data" # 从哪里定义的“Data”
top: "data"
top: "label"
include {
phase: TEST
}
transform_param{ # 从哪里定义
scale: 0.0039063
}
data_param{ # 从哪里定义
source: "MNIST_LMDB_PATH/mnist_test_lmdb"
batch_size: 100
backend: lmdb
}
}
# 内积层
layer{
name: "ip"
type: "InnerProduct" # 从哪里定义
bottom: "data"
top: "ip"
param{ # 从哪里定义
lr_mult: 1
}
param{
lr_mult: 2
}
inner_product_param{ # 从哪里定义
num_output: 10
weight_filler{
type: "xavier"
}
bias_filler{
type: "constant"
}
}
}
# 在Test阶段使用
layer{
name: "accuracy"
type: "Accuracy"
bottom: "ip"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}

layer{
name: "loss"
type: "SoftMaxWithLoss"
bottom: "ip"
bottom: "label"
top: "loss"
}

其中source提供LMDB数据的路径,提供绝对路径不用担心出错。

编辑lr_solver.prototxt

按照上述蓝图构建用于训练的网络和用于测试的网络。之后编辑训练超参数文件lr_solver.prototxt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 结构文件的路径,告诉caffe,构建蓝图在哪
net: "PATH/lr.prototxt"
test_iter: 100
# 每500次做一次测试
test_interval: 500
base_lr: 0.01
momentum: 0.9
weight_delay: 0.0005
lr_policy: "inv"
gamma: 0.0001
power: 0.75
max_iter: 10000
# 每迭代5000次拍个快照
snapshot: 5000
snapshot_prefix: "PATH/mnist/lrNet"
solver_mode: GPU

note: 想上添加type关键字,用来指定所使用的优化方法,如type: "Nesterov"type: "AdaGrad"type: "AdaDelta"等。默认使用SGD
有了数据有了模型就可以训练了:

1
2
CAFFE train \
--solver=PATH/lr_solver.prototxt

其中CAFFE,表示caffe_master提前编译好的caffe工具,就像在caffe_master中的命令./build/tools/caffe

总结,要想正确运行,必须保证所配置的路径是有效的:

  • 用于执行指令的build/tools/caffe命令的路径,
  • 训练超参数文件的路径lr_solver.prototxt
  • LMDB数据路径,
  • 模型结构超参数文件路径mylr.prototxt

对于Layer的类型

caffe现有的Layer type

1
2
3
4
5
6
7
8
9
10
known types: AbsVal, Accuracy, ArgMax, BNLL, BatchNorm, 
BatchReindex, Bias, Clip, Concat, ContrastiveLoss, Convolution,
Crop, Data, Deconvolution, Dropout, DummyData, ELU, Eltwise,
Embed, EuclideanLoss, Exp, Filter, Flatten, HDF5Data,
HDF5Output, HingeLoss, Im2col, ImageData, InfogainLoss,
InnerProduct, Input, LRN, LSTM, LSTMUnit, Log, MVN, MemoryData,
MultinomialLogisticLoss, PReLU, Parameter, Pooling, Power,
Python, RNN, ReLU, Reduction, Reshape, SPP, Scale, Sigmoid,
SigmoidCrossEntropyLoss, Silence, Slice, Softmax,
SoftmaxWithLoss, Split, Swish, TanH, Threshold, Tile, WindowData

当训练并测试完毕,会有模型文件和快照文件保存于当前目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
.
├── lr_solver.prototxt
├── mnist_test_lmdb
│   ├── data.mdb
│   └── lock.mdb
├── mnist_train_lmdb
│   ├── data.mdb
│   └── lock.mdb
├── my_lr_iter_10000.caffemodel
├── my_lr_iter_10000.solverstate
├── my_lr_iter_5000.caffemodel
├── my_lr_iter_5000.solverstate
└── mylr.prototxt

问题
这些关键字是在哪了与Layer的实现对应起来的呢?当将自己实现的Layer或其他组件键入到caffe源码中时,就需要在某处添加对应关键字。