Convolution+BatchNorm+Scale+Relu的组合模块在卷积后进行归一化,然后在放出非线性Relu层,可以加速训练收敛。但在推理时BatchNorm非常耗时,可以将训练时学习到的BatchNorm+Scale的线性变换参数融合到卷积层,替换原来的Convolution层中weight和bias,实现在不影响准确度的前提下加速预测时间。
一、Convolution+BatchNorm+Scale层在caffe中参数设置示例:
layer {
name: "Conv1"
type: "Convolution"
bottom: "Conv1"
top: "Conv2"
convolution_param {
num_output: 64
kernel_h:1
kernel_w:3
pad_h: 0
pad_w: 1
stride: 1
weight_filler {
type: "msra"
}
bias_term: false
}
}
layer {
name: "Conv2/bn"
type: "BatchNorm"
bottom: "Conv2"
top: "Conv2"
batch_norm_param {
use_global_stats: false
eps:1e-03
}
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
include {
phase: TRAIN
}
}
layer {
name: "Conv2/bn"
type: "BatchNorm"
bottom: "Conv2"
top: "Conv2"
batch_norm_param {
use_global_stats: true
eps:1e-03
}
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
include {
phase: TEST
}
}
layer {
name: "Conv2/bn/scale"
type: "Scale"
bottom: "Conv2"
top: "Conv2"
param {
lr_mult: 1
decay_mult: 0
}
param {
lr_mult: 1
decay_mult: 0
}
scale_param {
bias_term: true
}
}
二、解释说明:
1、Convolution层的设置:
- 权重: 强烈建议手动选择weight_filler初始化方式!对于Convolution+BatchNorm+Scale的组合模块,建议使用msra模式初始化。 (msra: short for Microsoft Research Asia or He-initialization, ref:Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification)。其他情况xavier初始化比较常用, xavier初始化可以根据输入和输出神经元的个数,自动地决定初始化值的大小。caffe中默认的weight_filler是constant, value:0, 这种默认的初始化方式得到的结果一般不好,我就遇到过使用了默认的weight_filler后导致图像语义分割错误地得到同色图片的情况。
- 因为BatchNorm层会减去平均值,所以convolution层的bias_term设置并没有意义。bias_term默认值为true, 默认的bias_filler也是constant, value:0。所以手动设置bias_term: false。
- 学习率和权重衰减系数,因为只有weight,没有bias,使用如下默认值(无需手动设置)
param {
lr_mult: 1
decay_mult: 1
}
2、BatchNorm层设置:
BatchNorm是进行归一化,计算
(1)
- use_global_stats在训练时设为false,神经网络只针对每一个batch的数据进行归一化操作,并每一步都利用滑移平均计算更新全局的mean和variance,但是并没有使用这两个全局的统计量;在测试时use_global_stats设为true,直接使用训练时计算好的全局mean和variance进行归一化;
- eps是在分母的var项上加一个小值,防止方差为0时出错;
- moving_average_fraction默认值为0.999,值越小表示较新迭代计算的mean和var权重更大,之前的迭代影响越小;
-
BatchNorm的三个参数mean,variance,moving_average_fraction。其中mean,variance是由输入数据计算直接计算得到的,moving_average_fraction是指定的,因此都与学习率和衰减率无关,设定
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
param {
lr_mult: 0
decay_mult: 0
}
参考资料:
https://github.com/hujie-frank/SENet/issues/26
https://gist.github.com/ducha-aiki/c0d1325f0cebe0b05c36
3、Scale层设置:
Scale是将BatchNorm得到的数据做线性变换:
(2)
bias_term在这里打开!学习率系数设定为1即可,无需decay_mult。
param {
lr_mult: 1
decay_mult: 0
}
param {
lr_mult: 1
decay_mult: 0
}
scale_param {
bias_term: true
}
三、融合BatchNorm+Scale层到卷积层进行推理加速
在推理时BatchNorm非常耗时,可以将训练时学习到的BatchNorm+Scale的线性变换参数融合到卷积层。具体方法为:
1、识别prototxt文件中的Batch和Scale层,直接删除(这要求BatchNorm和Scale层中top和bottom名保持一致,才能保证删除BatchNorm和Scale层后数据仍然能够正确传输,如上文中示例所用的方式)
2、修改caffemodel的weight,将convolution的bias_term修改为true,并用Convolution+BatchNorm+Scale的等效weight和bias去替换原来的weight和新打开的bias_term。convolution输出值为wx+b,作为BatchNorm层的输入,带入公式(1)(2)中,得到公式如下:
(3)
(4)
其中各参数的含义和定义同上文公式(1)(2)
3、另外,有些网络使用了dropout层防止过拟合,在预测时可直接删除dropout层,并不影响预测时数据的传输。
代码可以参考https://download.csdn.net/download/cxiazaiyu/10657938
代码中识别type类型符合BatchNorm, Scale和dropout的层对神经网络配置文件prototxt和权重文件caffemodel做相应修改。