①Data
数据层是所有模型的最底层,主要有transform_param{},与data_param{}两中参数设置,data_param{}是数据集来源与训练批大小一些的设置,这个因人而异,根据自己实际情况设置好就行。其中,batch_size是根据训练图像大小,GPU使用情况设置的。transform_param{}是数据预处理的一些设置,一般有:mirror,表示是否开启镜像,crop_size表示输入图像的大小, 如果将scale设置为0.00390625,实际上就是1/255,意味着将像素值归一到[0,1]中。
②Convolution
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1.0
decay_mult: 1.0
}
convolution_param {
num_output: 24
bias_term: false
pad: 1
kernel_size: 3
group: 1
stride: 2
weight_filler {
type: "msra"
}
dilation: 1
}
}
Bottom: 是指目前这层数据的流向来源层。有时只有一层,有时有多层。多层表示目前这层数据是由多层数据汇集的。
lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。
decay_mult: 权重衰减率,增加这个是为了避免模型过拟合。具体规范化对象是loss函数。
convolution_param{},这里面就是一些具体的卷积层参数,看名称就能知道是个啥,就不多解释了。
weight_filler{} 是对参数初始化类型的设置。
卷积过程:比如feature map 为a1* b1* N,filter 为a2* b2* M,则卷积的过程便意味着M个大小为a2* b2的filter 都要与N个feature map的各个大小为a2* b2的区域做卷积,然后相加作为一层卷积结果。
③ConvolutionDepthwise (深度可分离卷积,目前在轻量级网络中使用)
layer {
name: "resx1_match_DWconv"
type: "ConvolutionDepthwise"
bottom: "pool1"
top: "resx1_match_DWconv"
convolution_param {
num_output: 24
kernel_size: 5
stride: 2
pad: 1
bias_term: false
weight_filler {
type: "msra"
}
}
}
标准卷积过程: 对于一个三通道的输入图像,那么设置好kernel_size: 5之后,其实一个kernel真正的size为5* 5* 3,卷积过程是输入图像与kernel每个对应通道分别卷积,然后三个通道卷积结果相加,再经过激活函数映射得出来的数值,便是下一层feature map 对应的值。如果kernel个数是256的话,这个过程,需要学习出来的参数数量为:M=5* 5* 3* 256=19200。
Depthwise卷积过程(DW): 同样的输入图片,同样的卷积核个数,DW的卷积过程为:首先对每一个通道进行各自的卷积操作,需要学习的参数数量是M1=5* 5* 3,然后,对这批新的通道feature maps进行标准的1×1跨通道卷积操作,总共256个卷积核,则需要学习的参数数量是:M2=3* 1* 1* 256,。所以最终所有需要学习的参数数量是M=M1+M2=75+768=843。Amazing!!!!!
③BatchNorm 与 Scale
layer {
name: "conv5_bn"
type: "BatchNorm"
bottom: "conv5"
top: "conv5"
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
}
layer {
name: "conv5_scale"
bottom: "conv5"
top: "conv5"
type: "Scale"
scale_param {
filler {
value: 1
}
bias_term: true
bias_filler {
value: 0
}
}
}
BatchNorm 与 Scale一般是同时使用的,目的就是进行批归一化处理。其中BatchNorm是对输入进行归一化处理, Scale是对归一化的数据进行平移缩放,得到输出。
④ReLU
layer {
name: "conv1_relu"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
ReLU激活函数层,对卷积后的数据进行映射。
⑤Pooling
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
池化层,降维操作。
⑥Concat
layer {
name: "resx1_concat"
type: "Concat"
bottom: "resx1_match_conv"
bottom: "resx1_conv3"
top: "resx1_concat"
}
将多个bottom合并成一个top的过程。
将两个及以上的特征图按照在channel或num维度上进行拼接,一般都是channel上的拼接,并没有eltwise层的运算操作。如果说是在channel维度上进行拼接resx1_conv3和resx1_match_conv的话,首先除了channel维度可以不一样,其余维度必须一致(也就是num、H、W一致),这时候所做的操作仅仅是resx1_conv3 的channel k1加上resx1_match_conv的channel k2,Concat 层输出的blob可表示为:N*(k1+k2)HW。
实验室表明,NB之后进行Concat操作,效果会更好。
⑦ShuffleChannel(Shufflenet特有的层)
layer {
name: "shuffle1"
type: "ShuffleChannel"
bottom: "resx1_concat"
top: "shuffle1"
shuffle_channel_param {
group: 2
}
}
在分组卷积的基础上,打乱不同通道的排序,使得下一层的操作的输入能吸收来上一层不同组的内容,使得学习更佳均衡。
⑧Slice
layer{
name:"resx2_channelsplit"
type:"Slice"
bottom:"shuffle1"
top:"resx2_part1"
top:"resx2_part2"
slice_param {
slice_point: 24
}
}
与Concat层作用相反,它是将一个 bottom切分成多个top的过程。slice_point表示从哪里开切,即指定切分点。