当前位置: 代码迷 >> 综合 >> caffe 学习系列之c.prototxt配置文件解析 (3)
  详细解决方案

caffe 学习系列之c.prototxt配置文件解析 (3)

热度:125   发布时间:2023-10-12 00:31:06.0

    在上篇笔记中,已经记录了如何进行图片数据格式的转换和生成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
   
  • 1

    带两个参数:

    第一个参数: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配置文件有如下几种:

caffe 学习系列之c.prototxt配置文件解析 (3)

1.train_test.prototxt文件各层分析

    以之前用到的cifar10_quick_train_test.prototxt文件为例进行学习,一层一层进行分析。

part1:

name: "CIFAR10_quick"
   
  • 1

解释:

    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 }
}

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

解释:

  • 该layer为用于训练的数据层(Data Layers),具体参数意义如下: name: 表示该层的名称,可随意取;

  • type:层类型,如果是Data,表示数据来源于LevelDB或LMDB。根据数据的来源不同,数据层的类型也不同(后面会详细阐述)。一般在练习的时候,我们都是采用的LevelDB或LMDB数据,因此层类型设置为Data。

  • top或bottom:每一层用bottom来输入数据,用top来输出数据。如果只有top没有bottom,则此层只有输出,没有输入。反之亦然。如果有多个top或多个bottom,表示有多个blobs数据的输入和输出。

  • data 与 label: 在数据层中,至少有一个命名为data的top。如果有第二个top,一般命名为label。这种(data,label)配对是分类模型所必需的。

  • include:一般训练的时候和测试的时候,模型的层是不一样的。该层(layer)是属于训练阶段的层,还是属于测试阶段的层,需要用include来指定。如果没有include参数,则表示该层既在训练模型中,又在测试模型中。

  • transform_param:指定一些转换参数。mean_file参数指定生成的均值文件。

  • data_param:根据数据的来源不同进行不同的设置。该cifar10_quick_train_test.prototxt文件表示数据来源于LevelDB和LMDB。当然,数据也可以来源于内存、HDF5、图片和Windows。

它需要设置的参数如下:

  • source: 包含数据库的目录名称;

  • batch_size:每次处理的数据个数;

  • backend:选择是采用LevelDB还是LMDB, 默认是LevelDB。

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 }
}
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

解释:

    该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" }}
}
   
  • 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

解释:

    该layer为视觉层(Vision Layers),视觉层包括Convolution层、Pooling层、Local Response Normalization (LRN)层、im2col层等。由上可知,本层为视觉层的卷积层(Convolution Layer),它是卷积神经网络(CNN)的核心层。具体参数意义如下:

  • name、type、bottom、top参数意义同上,type参数表明层类型为Convolution层。

  • lr_mult:学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult,则第一个表示权值的学习率,第二个表示偏置项的学习率。一般偏置项的学习率是权值学习率的两倍。

  • 在后面的convolution_param中,我们可以设定卷积层的特有参数。

必须设置的参数:

  • num_output: 卷积核(filter)的个数;

  • kernel_size: 卷积核的大小。如果卷积核的长和宽不等,需要用kernel_h和kernel_w分别设定;

其它参数:

  • stride: 卷积核的步长,默认为1。也可以用stride_h和stride_w来设置;

  • pad: 扩充边缘,默认为0,不扩充。扩充的时候是左右、上下对称的,比如卷积核的大小为5*5,那么pad设置为2,则四个边缘都扩充2个像素,即宽度和高度都扩充了4个像素,这样卷积运算之后的特征图就不会变小。也可以通过pad_h和pad_w来分别设定;

  • weight_filler:权值初始化。默认为“constant”,值全为0,很多时候我们用”xavier”算法来进行初始化,也可以设置为”gaussian”;

  • bias_filler: 偏置项的初始化。一般设置为”constant”,值全为0;

  • bias_term:是否开启偏置项,默认为true, 开启;

  • group:分组,默认为1组。如果大于1,我们限制卷积的连接操作在一个子集内。如果我们根据图像的通道来分组,那么第i个输出分组只能与第i个输入分组进行连接。

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;
   
  • 1
  • 2

    如果设置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 }
}
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

解释:

    该layer为视觉层(Vision Layers)的池化层(Pooling Layer),该层是为了减少运算量和数据维度而设置的一种层。

  • name、type、bottom、top参数意义同上,type参数表明层类型为Pooling层。

  • 在后面的pooling_param中,我们可以设定池化层的特有参数。

必须设置的参数:

  • kernel_size: 池化的核大小。也可以用kernel_h和kernel_w分别设定。

其它参数:

  • pool: 池化方法,默认为MAX。目前可用的方法有MAX, AVE, 或STOCHASTIC;

  • pad: 和卷积层的pad的一样,进行边缘扩充。默认为0;

  • stride: 池化的步长,默认为1。一般我们设置为2,即不重叠。也可以用stride_h和stride_w来设置。

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;
   
  • 1
  • 2

    如果设置stride为2,前后两次卷积部分不重叠。100*100的特征图池化后,变成50*50。

part6:

layer {name: "relu1" type: "ReLU" bottom: "pool1" top: "pool1" }

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

解释:

    该layer为激活层(Activation Layers),在激活层中,对输入数据进行激活操作(实际上就是一种函数变换),是逐元素进行运算的。从bottom得到一个blob数据输入,运算后,从top输入一个blob数据。在运算过程中,没有改变数据的大小,即输入和输出的数据大小是相等的。

  • name、type、bottom、top参数意义同上,type参数表明层类型为使用ReLU激活函数的激活曾层。

可选参数:

  • negative_slope:默认为0。对标准的ReLU函数进行变化,如果设置了这个值,那么数据为负数时,就不再设置为0,而是用原始数据乘以negative_slope。

激活曾层的运算方法:

    输入: 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" }}
}

   
  • 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

解释:

    该layer为卷积层,同part4。

part7:

layer {name: "relu2" type: "ReLU" bottom: "conv2" top: "conv2" }

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

解释:

    该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" }}
}

   
  • 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

解释:

    该layer为卷积层,同part4。

part9:

layer {name: "relu3" type: "ReLU" bottom: "conv3" top: "conv3" }

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

解释:

    该layer为激活层,同part6。

part10:

layer {name: "pool3" type: "Pooling" bottom: "conv3" top: "pool3" pooling_param { pool: AVE kernel_size: 3 stride: 2 }
}

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

解释:

    该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" }}
}

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

解释:

    该layer为全连层(Inner Product),全连接层,把输入当作成一个向量,输出也是一个简单向量(把输入数据blobs的width和height全变为1)。

  • name、type、bottom、top参数意义同上,type参数表明层类型为全连层。

  • 在后面的inner_product_param中,我们可以设定卷积层的特有参数。

必须设置的参数:

  • num_output: 过滤器(filfter)的个数

其它参数:

  • weight_filler: 权值初始化。默认为“constant”,值全为0,很多时候我们用”xavier”算法来进行初始化,也可以设置为”gaussian”;

  • bias_filler: 偏置项的初始化。一般设置为”constant”,值全为0;

  • bias_term: 是否开启偏置项,默认为true, 开启。

全连层的计算方法:
    输入: 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" }}
}

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

解释:

    该layer为全连层,同part11。

part13:

layer {name: "accuracy" type: "Accuracy" bottom: "ip2" bottom: "label" top: "accuracy" include { phase: TEST }
}

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

解释:

    该layer为精度输出层(Accuracy Layer),该层输出分类(预测)精确度,只有test阶段才有,include参数表型测试阶段使用。

part14:

layer {name: "loss" type: "SoftmaxWithLoss" bottom: "ip2" bottom: "label" top: "loss" }

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

解释:

    该layer为softmax-loss层,sotfmax-loss计算公式为:

caffe 学习系列之c.prototxt配置文件解析 (3)

    感觉这类似于决策树中用到的香农熵的计算。

  • name、type、bottom、top参数意义同上,type参数表明层类型为softmax-loss层。

2.结尾

    在Caffe中,不仅这些层,还有很多层,并且在持续更新中,这里不在继续讲解。

    更为详细的内容,可查看官网:

    URL:http://caffe.berkeleyvision.org/tutorial/layers.html

    下篇笔记将记录如何使用caffe提供的python接口编写train.protxt和test.prototxt文件。




    参考:[1](http://blog.csdn.net/c406495762)
  相关解决方案