BatchNorm在预测的时候为什么要去掉?



  • 简单的分享一下,很多人在做网络推理的时候,并不会考虑batchnorm的作用,拿别人的网络来训练,训练完了之后预测的时候也直接预测。这是不对的,因为batchnorm本身在预测的时候没有任何作用,它实在训练的时候起到了一个归一话加速收敛的作用。

    batchnorm合并的必要性

    那么为什么要将batchnorm合并呢?一般放置在卷积层(conv层)或者全连接层之后,将数据归一化并加速了训练拟合速度。但是bn层虽然在深度学习模型训练时起到了一定的积极作用,但是在预测时因为凭空多了一些层,影响了整体的计算速度并占用了更多内存或者显存空间。所以我们设想如果能将bn层合并到相邻的卷积层或者全连接层之后就好了,于是就有了这篇文章所提到的工作。

    batchnorm合并的方法

    batchnorm以后iban其实放置在conv或者pooling之后。合并的方式就得分开进行。

    1. 如果是在conv之后
      思考一下,假如是在conv之后,原来bn层的参数,也就是均值和方差,可以直接合并到卷积参数里面去,这样计算的时候就不用再进行这一步的计算了。看看代码是如何实现的:
                    mean = bn[0].data
                    var = bn[1].data
                    scalef = bn[2].data
    
                    scales = scale[0].data
                    shift = scale[1].data
    
                    if scalef != 0:
                        scalef = 1. / scalef
                    mean = mean * scalef
                    var = var * scalef
                    rstd = 1. / np.sqrt(var + 1e-5)
                    if bn_maps[key]["type"] == "Convolution": 
                        rstd1 = rstd.reshape((channels,1,1,1))
                        scales1 = scales.reshape((channels,1,1,1))
                        wt = wt * rstd1 * scales1
                    else:
                        rstd1 = rstd.reshape((1, channels,1,1))
                        scales1 = scales.reshape((1, channels,1,1))
                        wt = wt * rstd1 * scales1
                    bias = (bias - mean) * rstd * scales + shift
                    
                    nobn.params[key][0].data[...] = wt
                    nobn.params[key][1].data[...] = bias
    

    这个是caffe的合并操作。这个代码在MobileNet-SSD里面有:https://github.com/chuanqi305/MobileNet-SSD/blob/master/merge_bn.py
    2. 如果是在pooling之后
    pooling之后的操作差不多,具体大家可以探索一下。

    这样你的bn曾合并之后速度可以增加很多,有其实bn层很多的网络,将bn层合并是一个不可或缺的操作,否则你推理的速度将会大大的减慢。



  • @yzhcode 可以的



  • batchnorm合并的方法受教


登录后回复