层结构,是神经网络(Neural Networks)建模和计算的最基本单元。由于神经网络有不同的层结构,不同类型的层又有不同的参数。所以,对Caffe的每一层配置都不一样,而层结构和参数都预先定义在prototxt文件中,在此,我们对最新版Caffe模型的层结构做一个简要的总结。
如需要转载,请注明出处:http://blog.csdn.net/ws_20100
由于水平有限,如果有错误,敬请指正。
视觉层通常将图像作为输入,并将处理后的图像作为输出。一个典型的图像,一般具有一个通道( c=1 ,灰度图像)或三个通道( c=3 ,RGB图像)。而在本文中,一幅图像的区分特征是它的空间结构:通常一幅图像具有一个较大的高度 h>1 和宽度 w>1 。这种二维的几何特性很自然地引领我们去恰当地处理图像输入。通常,视觉层对输入图像的局部区域进行操作,并产生与之对应的局部输出。相比而言,其他层(除了极个别例外)会忽略输入图像的空间结构,而将其作为一个维度为 chw 的”大向量”进行处理。
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
# learning rate and decay multipliers for the filters
param { lr_mult: 1 decay_mult: 1 }
# learning rate and decay multipliers for the biases
param { lr_mult: 2 decay_mult: 0 }
convolution_param {
num_output: 96 # learn 96 filters
kernel_size: 11 # each filter is 11x11
stride: 4 # step 4 pixels between each filter application
weight_filler {
type: "gaussian" # initialize the filters from a Gaussian
std: 0.01 # distribution with stdev 0.01 (default mean: 0)
}
bias_filler {
type: "constant" # initialize the biases to zero (0)
value: 0
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3 # pool over a 3x3 region
stride: 2 # step two pixels (in the bottom blob) between pooling regions
}
}
局部响应正则化层,通过对局部输入区域进行正则化,以达到一种”侧抑制”的作用。在ACROSS_CHANNELS模式中,局部区域扩展到了相邻通道,但是没有空间扩展(例如,它们的大小为local_size x 1 x 1)。在WITHIN_CHANNEL模式中,局部区域存在空间扩展,但是是在单独的通道中(例如,它们的大小为1 x local_size x local_size)。每个输入值要除以 (1+(α/n)∑ix2i)β ,其中, n 是局部区域的尺寸,并对以该值为中心的区域进行求和(如果需要会增加0填充)。
对于将图像转化为列向量的变换,im2col是一个很有用的工具,而你多数情况下并不需要知道它。im2col将所有的块布局到一个矩阵,将Caffe原始的卷积操作转换为矩阵乘法。
损耗层通过比较输出和目标的差值并最小化代价来驱动学习。损耗自身通过前向传播计算,而损耗的梯度 w.r.t 通过反向传播计算。
softmax loss层会计算它输入数据softmax的多项式逻辑损耗。在概念上等效于,在多项式逻辑loss层之后级联一个softmax层。但在数值上可以提供更为稳定的梯度。
Euclidean loss层会计算两个输入差值的平方和。公式如下:
12N∑Ni=1||x1i−x2i||22
# L1 Norm
layer {
name: "loss"
type: "HingeLoss"
bottom: "pred"
bottom: "label"
}
# L2 Norm
layer {
name: "loss"
type: "HingeLoss"
bottom: "pred"
bottom: "label"
top: "loss"
hinge_loss_param {
norm: L2
}
}
hinge loss层计算一个一对多的hinge损耗或hinge损耗的平方。
Accuracy层用来计算输出和目标输出的正确率,事实上这不是一个loss层,而且没有后向传播这一步。
通常,激励层或称为神经元层,是元素级的操作,输入底层blob,并在顶层产生相同大小的blob。在以下介绍的激励层中,我们忽略输入和输出的大小,统一定义为:
layer {
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
对于给定的一个输入值x,如果x > 0,ReLU层的输出为x,如果x < 0,ReLU层的输出为negative_slope * x。如果negative_slope参数没有设置,它就等价于标准ReLU函数: max(x,0) 。它也支持原地计算,这意味着底层blob和顶层blob可以相同,以减少资源消耗。
layer {
name: "encode1neuron"
bottom: "encode1"
top: "encode1neuron"
type: "Sigmoid"
}
Sigmoid层对每个输入元素x计算其 sigmoid(x) 值作为输出。
layer {
name: "layer"
bottom: "in"
top: "out"
type: "TanH"
}
TanH层对每个输入元素x计算其 tanh(x) 值作为输出。
layer {
name: "layer"
bottom: "in"
top: "out"
type: "AbsVal"
}
AbsVal层对每个输入元素x计算其 abs(x) 值作为输出。
layer {
name: "layer"
bottom: "in"
top: "out"
type: "Power"
power_param {
power: 1
scale: 1
shift: 0
}
}
Power层对每个输入元素x计算其 (shift+scale∗x)power 值作为输出。
layer {
name: "layer"
bottom: "in"
top: "out"
type: BNLL
}
BNLL(binomial normal log likelihood)层对每个输入元素x计算其 log(1+ex) 值作为输出。
数据通过数据层进入Caffe:它们处于网络的底部。数据可以来自于有效的数据库(LevelDB或者LMDB),直接来自于内存,或者,当效率不是关键因素时,数据可以来自于磁盘的HDF5文件或通用的图像格式文件。
通过指定TransformationParameters可以进行常用的输入预处理(减去均值、缩放、随机裁剪、镜像处理)。
memory data层直接从内存中读取数据,而不进行拷贝操作。为了使用它,必须调用MemoryDataLayer::Reset(C++中)或者Net.set_input_arrays(Python中),使用一个四维行向量来指定连续数据的来源,并且每次只读batch_size大小的数据块。
layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "label"
hdf5_data_param {
source: "examples/CNN/train.txt"
batch_size: 128
}
include: { phase: TRAIN }
}
layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "label"
hdf5_data_param {
source: "examples/CNN/test.txt"
batch_size: 2
}
include: { phase: TEST }
}
HDF5 output层与这节中的其他层相反,它将输入blob写入到磁盘中。
DummyData用于开发和调试。请见DummyDataParameter
layer {
name: "fc8"
type: "InnerProduct"
# learning rate and decay multipliers for the weights
param { lr_mult: 1 decay_mult: 1 }
# learning rate and decay multipliers for the biases
param { lr_mult: 2 decay_mult: 0 }
inner_product_param {
num_output: 1000
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
bottom: "fc7"
top: "fc8"
}
InnerProduct层(通常也称为全连接层),将输入数据以简单的向量形式进行处理,并且输出一个简单的向量(blob的高度,宽带为1)。
Splitting层可以把一个输入blob分离成多个输出blobs。这个用在需要把一个blob输入到多个输出层的情形。
Flattening层是把一个输入的大小为n * c * h * w的数据变成一个简单的向量,其大小为 n * (c * h * w)。
layer {
name: "reshape"
type: "Reshape"
bottom: "input"
top: "output"
reshape_param {
shape {
dim: 0 # copy the dimension from below
dim: 2
dim: 3
dim: -1 # infer it from the other dimensions
}
}
}
Resharp层可以用于改变输入的维度,而不改变其自身的数据。和Flatten层一样,仅仅改变维度,在过程中不涉及数据拷贝操作。输出维度通过ReshapeParam的proto文件指定。直接使用正数设置对应的输出blob维度。另外,两个特殊的值也可以用于设置任何目标维度值。
- 0 代表“拷贝底层相应的维度“。就是说,如果给定dim: 0作为第一个维度,则底层第一个维度如果是2,顶层第一个维度也会是2。
- -1 代表“从其他维度推断“。它的性质有点类似于numpy中的-1,或者MATLAB的resharp中的 [] :计算出的维度与底层保持相同的整体元素数。多数情况下,-1可以用于resharp操作。
另一个例子:指定resharp_param { sharp { dim: 0 dim: -1 } },这样,这层的性质与Flatten层完全一样。
layer {
name: "concat"
bottom: "in1"
bottom: "in2"
top: "out"
type: "Concat"
concat_param {
axis: 1
}
}
Concat层将串连多个输入blob,成为一个单一的输出blob。
Slice层将一个输入层根据切割指标给定的维度(现在只有num和channel)切割成多个输出层。
layer {
name: "slicer_label"
type: "Slice"
bottom: "label"
## Example of label with a shape N x 3 x 1 x 1
top: "label1"
top: "label2"
top: "label3"
slice_param {
axis: 1
slice_point: 1
slice_point: 2
}
}
axis指定目标轴;slice_point指定选定维数的索引(索引的数量必须等于blob数量减去一)。
Caffe下载地址:https://github.com/BVLC/caffe