运行平台: Ubuntu14.04
在上篇笔记中,已经记录了如何进行图片数据格式的转换和生成txt列表清单文件。本篇笔记主要记录如何计算图片数据的均值和理解prototxt配置文件中各个层的参数。
Caffe主要处理两种形式的数据流:
图像和标签在网络上的传输,随着网络的传输,它们转化更高层次的表示,最终以得分或者概率值的形式输出。
第二种数据流,主要保存各个网络层的参数,比如卷积层的weights和bias. 这些值是随着的网络的训练过程不断变化的。
一、二进制格式的均值计算
图片减去均值后,再进行训练和测试,会提高速度和精度。因此,一般在各种模型中都会有这个操作。不过此步骤不是必须的,如果使用txt列表清单文件,则可以不使用db文件和均值文件,此部分内容会在后续进行讲解,此乃后话。
那么这个均值怎么来的呢,实际上就是计算所有训练样本的平均值,计算出来后,保存为一个均值文件,在以后的测试中,就可以直接使用这个均值来相减,而不需要对测试图片重新计算。
在训练过程中,caffe使用的均值数据格式是binaryproto,它是一个二进制格式文件。作者为我们提供了一个计算均值的文件compute_image_mean.cpp,放在caffe根目录下的tools文件夹里面。编译caffe后,生成的可执行文件放在 build/tools/ 目录下,我们可以直接在caffe根目录中使用如下指令:
build/tools/compute_image_mean my-caffe-project/img_train_lmdb my-caffe-project/mean.binaryproto
带两个参数:
第一个参数:my-caffe-project /img_train_lmdb , 表示需要计算均值的数据,格式为lmdb的训练数据。
第二个参数:my-caffe-project /mean.binaryproto, 计算出来的二进制格式的均值文件。
二、prototxt配置文件
要运行caffe,需要先创建一个模型(model),如比较常用的Lenet,Alex等, 而一个模型由多个屋(layer)构成,每一层又由许多参数组成。所有的参数都定义在caffe.proto这个文件中。要熟练使用caffe,最重要的就是学会配置文件(prototxt)的编写。我们可以直接使用vim编写prototxt文件,也可以使用caffe的python接口编写这个配置文件。但无论如何,都应该先对于模型的各个层有所了解。
层有很多种类型,比如Data,Convolution,Pooling等,层之间的数据流动是以Blobs的方式进行。
caffe一般使用的prototxt配置文件有如下几种:
1.train_test.prototxt文件各层分析
以之前用到的cifar10_quick_train_test.prototxt文件为例进行学习,一层一层进行分析。
part1:
name: "CIFAR10_quick"
解释:
name:表示该prototxt文件的名称,可以随意取。
part2:
layer {
name: "cifar"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
mean_file: "examples/cifar10/mean.binaryproto"
}
data_param {
source: "examples/cifar10/cifar10_train_lmdb"
batch_size: 100
backend: LMDB
}
}
解释:
它需要设置的参数如下:
part3:
layer {
name: "cifar"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
mean_file: "examples/cifar10/mean.binaryproto"
}
data_param {
source: "examples/cifar10/cifar10_test_lmdb"
batch_size: 100
backend: LMDB
}
}
解释:
该layer为用于测试的数据层(Data Layers)。参数意义同part2。
part4:
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
pad: 2
kernel_size: 5
stride: 1
weight_filler {
type: "gaussian"
std: 0.0001
}
bias_filler {
type: "constant"
}
}
}
解释:
该layer为视觉层(Vision Layers),视觉层包括Convolution层、Pooling层、Local Response Normalization (LRN)层、im2col层等。由上可知,本层为视觉层的卷积层(Convolution Layer),它是卷积神经网络(CNN)的核心层。具体参数意义如下:
必须设置的参数:
其它参数:
Convolution层运算方法:
输入: n*c0*w0*h0 输出: n*c1*w1*h1
其中,c1就是参数中的num_output,生成的特征图个数:
w1=(w0+2*pad-kernel_size)/stride+1;
h1=(h0+2*pad-kernel_size)/stride+1;
如果设置stride为1,前后两次卷积部分存在重叠。如果设置pad=(kernel_size-1)/2,则运算后,宽度和高度不变。
part5:
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
解释:
该layer为视觉层(Vision Layers)的池化层(Pooling Layer),该层是为了减少运算量和数据维度而设置的一种层。
必须设置的参数:
其它参数:
pooling层的运算方法基本是和卷积层是一样的。
输入: n*c*w0*h0 输出: n*c*w1*h1
和卷积层的区别就是其中的c保持不变:
w1=(w0+2*pad-kernel_size)/stride+1;
h1=(h0+2*pad-kernel_size)/stride+1;
如果设置stride为2,前后两次卷积部分不重叠。100*100的特征图池化后,变成50*50。
part6:
layer {
name: "relu1"
type: "ReLU"
bottom: "pool1"
top: "pool1"
}
解释:
该layer为激活层(Activation Layers),在激活层中,对输入数据进行激活操作(实际上就是一种函数变换),是逐元素进行运算的。从bottom得到一个blob数据输入,运算后,从top输入一个blob数据。在运算过程中,没有改变数据的大小,即输入和输出的数据大小是相等的。
可选参数:
激活曾层的运算方法:
输入: n*c*h*w 输出: n*c*h*w
常用的激活函数有sigmoid, tanh,relu等。该激活曾使用ReLU激活函数,ReLU层支持in-place计算,这意味着bottom的输出和输入相同以避免内存的消耗。
part7:
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
pad: 2
kernel_size: 5
stride: 1
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
}
}
}
解释:
该layer为卷积层,同part4。
part7:
layer {
name: "relu2"
type: "ReLU"
bottom: "conv2"
top: "conv2"
}
解释:
该layer为池化层,同part5。
part8:
layer {
name: "conv3"
type: "Convolution"
bottom: "pool2"
top: "conv3"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 64
pad: 2
kernel_size: 5
stride: 1
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
}
}
}
解释:
该layer为卷积层,同part4。
part9:
layer {
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
}
解释:
该layer为激活层,同part6。
part10:
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3"
top: "pool3"
pooling_param {
pool: AVE
kernel_size: 3
stride: 2
}
}
解释:
该layer为池化层,同part5。
part11:
layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool3"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 64
weight_filler {
type: "gaussian"
std: 0.1
}
bias_filler {
type: "constant"
}
}
}
解释:
该layer为全连层(Inner Product),全连接层,把输入当作成一个向量,输出也是一个简单向量(把输入数据blobs的width和height全变为1)。
必须设置的参数:
其它参数:
全连层的计算方法: 输入: n*c0*h*w 输出: n*c1*1*1
全连接层实际上也是一种卷积层,只是它的卷积核大小和原数据大小一致。因此它的参数基本和卷积层的参数一样。
part12:
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: "gaussian"
std: 0.1
}
bias_filler {
type: "constant"
}
}
}
解释:
该layer为全连层,同part11。
part13:
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
解释:
该layer为精度输出层(Accuracy Layer),该层输出分类(预测)精确度,只有test阶段才有,include参数表型测试阶段使用。
part14:
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}
解释:
该layer为softmax-loss层,sotfmax-loss计算公式为:
感觉这类似于决策树中用到的香农熵的计算。
2.结尾
在Caffe中,不仅这些层,还有很多层,并且在持续更新中,这里不在继续讲解。
更为详细的内容,可查看官网:
URL:http://caffe.berkeleyvision.org/tutorial/layers.html
下篇笔记将记录如何使用caffe提供的python接口编写train.protxt和test.prototxt文件。