批量归一化-BN层(Batch Normalization)
随机梯度下降法(SGD)对于训练深度网络简单高效,但是它有个毛病,就是需要我们人为的去选择参数,比如学习率、参数初始化、权重衰减系数、Drop out比例等。这些参数的选择对训练结果至关重要,以至于我们很多时间都浪费在这些的调参上。那么使用BN层之后,你可以不需要那么刻意的慢慢调整参数。(详见论文《Batch Normalization_ Accelerating Deep Network Training by Reducing Internal Covariate Shift》 )。
在神经网络训练网络模型时,BN层能够加速网络收敛,并且能够控制过拟合现象的发生,一般放在卷积层之后,激活层之前。BN层将数据归一化后,能够有效解决梯度消失与梯度爆炸问题。虽然BN层在训练时起到了积极作用,然而,在网络Inference时多了一些层的运算,影响了模型的性能,且占用了更多的内存或者显存空间。因此,有必要将 BN 层的参数合并到卷积层,减少计算来提升模型Inference的速度。
• BN(Batch Normalization)层能够加速网络收敛,并且能够控制过拟合,一般放在卷积层之后。
• 虽然 BN 层在训练时起到了积极作用,但在网络前向推理时增加了运算,影响了模型的性能,且占用了更多的内存或者显存空间。
• 将 BN 层的参数合并到卷积层,来提升模型前向推断的速度。
其中x_out为BN计算结果,x_conv为BN前面的卷积计算结果,其余的参数都保存在.weights文件中。
合并卷积层与BN层:
卷积+BN:
此时.weights文件中的参数只剩下权值w和偏置b,合并后的参数要写到新的.weights文件中,注意再次运行Inference代码时,记得将.cfg文件中所有的batch_normalize=1改为batch_normalize=0。
部分代码实现
保存合并后的参数,【文件parser.c中增加代码】
//保存convolutional_weights
void save_convolutional_weights_nobn(layer l, FILE *fp)
{
if(l.binary){
//save_convolutional_weights_binary(l, fp);
//return;
}
#ifdef GPU