在手写体识别例程中,使用的网络模型为LeNet-5模型,这个模型的描述文件为lenet_train_test.prototxt,它位于caffe根目录中的/examples/mnist/目录下。
下面,我们对这个描述文件进行分析一下,看看它里边是如何描述网络模型的。打开文件,第一行如下所示。
name: "LeNet"
它定义了网络的名字为LeNet。在这一行的下方,就是若干个layer,没有而外的东西,如下
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
}
}
这是网络模型的第一个层,首先定义了层的名字为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格式数据。
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
}
}
这一层和上一层基本是一样的,只是这一层用作测试阶段,数据来源为测试集的数据库,测试样本数为100。
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"
}
}
}
这一层是一个卷积层,它的名字为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。
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
这一层为池化层,它的名字为pool1,类型为Pooling,即池化层。输入为上一个卷积层的输出blob,输出blob为pool1。pooling_param中定义了池化层的参数,pool: MAX表示使用最大值下采样方法,kernel_size表示下采样窗口尺寸2X2,stride表示下采样跳跃间隔为2X2。
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
这一层为一个新的卷积层,它的输入blob为pool1,输出blob为conv2,其它参数与conv1中的含义相同,只是取值略有不同。
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
这一层是一个新的池化层,输入blob为conv2,输出blob为pool2。
layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
这一层是一个全连接层,名字为ip1,输入blob为pool2,输出blob为ip1。定义的两个参数与卷积层的定义是一样的。inner_product_param中定义了全连接层的参数,输出数量为500,weight_filler和bias_filler参数与卷积层中的定义一样。
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
这一层是非线性层,非线性化采用的是ReLU方法,输入和输出blob都是ip1,即将输入的ip1非线性化后输出。
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"
}
}
}
这一层是一个新的全连接层,名字为ip2,输入blob为ip1,输出blob为ip2,输出数量为10。
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
这一层为准确率层,只在测试阶段有效,输入blob为ip2和label,输出为accuracy,这一层的作用是将网络的最终识别输出与图片的标签进行比较,并统计准确率。
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}
这一层是网络的最后一层,是损失层,损失函数采用SoftmaxLoss,输入blob为ip2和label,输出blob为loss。
上面就是lenet-5的完整描述。