在手写体识别例程中,使用的网络模型为LeNet-5模型,这个模型的描述文件为lenet_train_test.prototxt,它位于caffe根目录中的/examples/mnist/目录下。
下面,我们对这个描述文件进行分析一下,看看它里边是如何描述网络模型的。打开文件,第一行如下所示。
1
2 1name: "LeNet"
2
它定义了网络的名字为LeNet。在这一行的下方,就是若干个layer,没有而外的东西,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1layer {
2 name: "mnist"
3 type: "Data"
4 top: "data"
5 top: "label"
6 include {
7 phase: TRAIN
8 }
9 transform_param {
10 scale: 0.00390625
11 }
12 data_param {
13 source: "examples/mnist/mnist_train_lmdb"
14 batch_size: 64
15 backend: LMDB
16 }
17}
18
这是网络模型的第一个层,首先定义了层的名字为mnist,类型为Data,即数据,top表示层的输出blob,分别为data和label。关于blob是什么,我们会有专门的文章来讲解,这里我们只用知道blob是类似一种数据类型。
include {
phase: TRAIN
}
这段表示,这一层只在训练阶段起作用,
transform_param {
scale: 0.00390625
}
这段代码表示,数据变换使用的缩放因子为0.00390625
最后,data_param中是数据参数,包括:source指定数据的存储位置,batch_size指定训练采用的样本数,这里每次训练采用64幅图片。backend表示数据类型为lmdb格式数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1layer {
2 name: "mnist"
3 type: "Data"
4 top: "data"
5 top: "label"
6 include {
7 phase: TEST
8 }
9 transform_param {
10 scale: 0.00390625
11 }
12 data_param {
13 source: "examples/mnist/mnist_test_lmdb"
14 batch_size: 100
15 backend: LMDB
16 }
17}
18
这一层和上一层基本是一样的,只是这一层用作测试阶段,数据来源为测试集的数据库,测试样本数为100。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 1layer {
2 name: "conv1"
3 type: "Convolution"
4 bottom: "data"
5 top: "conv1"
6 param {
7 lr_mult: 1
8 }
9 param {
10 lr_mult: 2
11 }
12 convolution_param {
13 num_output: 20
14 kernel_size: 5
15 stride: 1
16 weight_filler {
17 type: "xavier"
18 }
19 bias_filler {
20 type: "constant"
21 }
22 }
23}
24
这一层是一个卷积层,它的名字为conv1,类型是Convolution卷积网络层,bottom表示这一层的输入,输入blob为data,即上一层的输出。这一层的输出blob为conv1。
这一层接下来定义了两个参数,第一个参数为权值学习速率倍乘因子,1表示保持与全局参数一致;第二个参数为bias学习速率倍乘因子,是全局参数的2倍。
接下来convolution_param中定义的是卷积层的参数,num_output表示输出特征图数量为20,kernel_size表示卷积核的尺寸为5X5,stride表示卷积输出跳跃间隔,1表示连续输出无跳跃。weight_filler中定义了权值使用xavier填充器,bias_filler中定义了bias使用常数填充器,默认为0。
1
2
3
4
5
6
7
8
9
10
11
12 1layer {
2 name: "pool1"
3 type: "Pooling"
4 bottom: "conv1"
5 top: "pool1"
6 pooling_param {
7 pool: MAX
8 kernel_size: 2
9 stride: 2
10 }
11}
12
这一层为池化层,它的名字为pool1,类型为Pooling,即池化层。输入为上一个卷积层的输出blob,输出blob为pool1。pooling_param中定义了池化层的参数,pool: MAX表示使用最大值下采样方法,kernel_size表示下采样窗口尺寸2X2,stride表示下采样跳跃间隔为2X2。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 1layer {
2 name: "conv2"
3 type: "Convolution"
4 bottom: "pool1"
5 top: "conv2"
6 param {
7 lr_mult: 1
8 }
9 param {
10 lr_mult: 2
11 }
12 convolution_param {
13 num_output: 50
14 kernel_size: 5
15 stride: 1
16 weight_filler {
17 type: "xavier"
18 }
19 bias_filler {
20 type: "constant"
21 }
22 }
23}
24
这一层为一个新的卷积层,它的输入blob为pool1,输出blob为conv2,其它参数与conv1中的含义相同,只是取值略有不同。
1
2
3
4
5
6
7
8
9
10
11
12 1layer {
2 name: "pool2"
3 type: "Pooling"
4 bottom: "conv2"
5 top: "pool2"
6 pooling_param {
7 pool: MAX
8 kernel_size: 2
9 stride: 2
10 }
11}
12
这一层是一个新的池化层,输入blob为conv2,输出blob为pool2。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 1layer {
2 name: "ip1"
3 type: "InnerProduct"
4 bottom: "pool2"
5 top: "ip1"
6 param {
7 lr_mult: 1
8 }
9 param {
10 lr_mult: 2
11 }
12 inner_product_param {
13 num_output: 500
14 weight_filler {
15 type: "xavier"
16 }
17 bias_filler {
18 type: "constant"
19 }
20 }
21}
22
这一层是一个全连接层,名字为ip1,输入blob为pool2,输出blob为ip1。定义的两个参数与卷积层的定义是一样的。inner_product_param中定义了全连接层的参数,输出数量为500,weight_filler和bias_filler参数与卷积层中的定义一样。
1
2
3
4
5
6
7 1layer {
2 name: "relu1"
3 type: "ReLU"
4 bottom: "ip1"
5 top: "ip1"
6}
7
这一层是非线性层,非线性化采用的是ReLU方法,输入和输出blob都是ip1,即将输入的ip1非线性化后输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 1layer {
2 name: "ip2"
3 type: "InnerProduct"
4 bottom: "ip1"
5 top: "ip2"
6 param {
7 lr_mult: 1
8 }
9 param {
10 lr_mult: 2
11 }
12 inner_product_param {
13 num_output: 10
14 weight_filler {
15 type: "xavier"
16 }
17 bias_filler {
18 type: "constant"
19 }
20 }
21}
22
这一层是一个新的全连接层,名字为ip2,输入blob为ip1,输出blob为ip2,输出数量为10。
1
2
3
4
5
6
7
8
9
10
11 1layer {
2 name: "accuracy"
3 type: "Accuracy"
4 bottom: "ip2"
5 bottom: "label"
6 top: "accuracy"
7 include {
8 phase: TEST
9 }
10}
11
这一层为准确率层,只在测试阶段有效,输入blob为ip2和label,输出为accuracy,这一层的作用是将网络的最终识别输出与图片的标签进行比较,并统计准确率。
1
2
3
4
5
6
7
8 1layer {
2 name: "loss"
3 type: "SoftmaxWithLoss"
4 bottom: "ip2"
5 bottom: "label"
6 top: "loss"
7}
8
这一层是网络的最后一层,是损失层,损失函数采用SoftmaxLoss,输入blob为ip2和label,输出blob为loss。
上面就是lenet-5的完整描述。