首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Caffe学习笔记(三):cifar10_quick_train_test.prototxt配置文件分析

运行平台: Ubuntu14.04

    在上篇笔记中,已经记录了如何进行图片数据格式的转换和生成txt列表清单文件。本篇笔记主要记录如何计算图片数据的均值和理解prototxt配置文件中各个层的参数。

    Caffe主要处理两种形式的数据流:

    图像和标签在网络上的传输,随着网络的传输,它们转化更高层次的表示,最终以得分或者概率值的形式输出。

    第二种数据流,主要保存各个网络层的参数,比如卷积层的weights和bias. 这些值是随着的网络的训练过程不断变化的。

一、二进制格式的均值计算

    图片减去均值后,再进行训练和测试,会提高速度和精度。因此,一般在各种模型中都会有这个操作。不过此步骤不是必须的,如果使用txt列表清单文件,则可以不使用db文件和均值文件,此部分内容会在后续进行讲解,此乃后话。

    那么这个均值怎么来的呢,实际上就是计算所有训练样本的平均值,计算出来后,保存为一个均值文件,在以后的测试中,就可以直接使用这个均值来相减,而不需要对测试图片重新计算。

    在训练过程中,caffe使用的均值数据格式是binaryproto,它是一个二进制格式文件。作者为我们提供了一个计算均值的文件compute_image_mean.cpp,放在caffe根目录下的tools文件夹里面。编译caffe后,生成的可执行文件放在 build/tools/ 目录下,我们可以直接在caffe根目录中使用如下指令:

代码语言:c
复制
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:

代码语言:javascript
复制
name: "CIFAR10_quick"

解释:

    name:表示该prototxt文件的名称,可以随意取。

part2:

代码语言:javascript
复制
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
  }
}

解释:

  • 该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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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)的核心层。具体参数意义如下:

  • 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,生成的特征图个数:

代码语言:javascript
复制
 w1=(w0+2*pad-kernel_size)/stride+1;
 h1=(h0+2*pad-kernel_size)/stride+1;

    如果设置stride为1,前后两次卷积部分存在重叠。如果设置pad=(kernel_size-1)/2,则运算后,宽度和高度不变。

part5:

代码语言:javascript
复制
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}

解释:

    该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保持不变:

代码语言:javascript
复制
 w1=(w0+2*pad-kernel_size)/stride+1;
 h1=(h0+2*pad-kernel_size)/stride+1;

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

part6:

代码语言:javascript
复制
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "pool1"
  top: "pool1"
}

解释:

    该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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
layer {
  name: "relu2"
  type: "ReLU"
  bottom: "conv2"
  top: "conv2"
}

解释:

    该layer为池化层,同part5。

part8:

代码语言:javascript
复制
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:

代码语言:javascript
复制
layer {
  name: "relu3"
  type: "ReLU"
  bottom: "conv3"
  top: "conv3"
}

解释:

    该layer为激活层,同part6。

part10:

代码语言:javascript
复制
layer {
  name: "pool3"
  type: "Pooling"
  bottom: "conv3"
  top: "pool3"
  pooling_param {
    pool: AVE
    kernel_size: 3
    stride: 2
  }
}

解释:

    该layer为池化层,同part5。

part11:

代码语言:javascript
复制
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)。

  • 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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}

解释:

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

part14:

代码语言:javascript
复制
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}

解释:

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

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

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

2.结尾

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

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

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

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

下一篇
举报
领券