神经网络除了量化以外,还可以进行剪枝。

某些剪枝的方法,一般是先训练预训练模型,然后进行剪枝,再次训练剪枝以后的网络,然后剪枝-训练不断重复,每次剪枝以后得到的网络结构,参数量更少,所以某些剪枝方法可以得到更优化的网络结构。

这个文篇使用BN层参数γ,由于每个输出的每个channel都有各自的参数γ和β,可以使用γ值来判断不同channel的重要程度。γ值在某些程度可以看作是标准差,标准差反映了输入channel的分布情况,γ值越小代表这个channel的特征不显著,特征不显著那么这个channel就不那么重要,可以被裁剪掉。

在初始训练的时候,使用了L1正则对参数γ进行离散化。实际对γ进行正则化的时候,使用了系数args.s,一般是等于0.0001或者0.001,最后一行代码,torch.sign是拿到符号位,正数等于1,负数等于-1,0等于0。这里的m.weight.data就是BN层的参数γ。

L1正则就是取绝对值,

神经网络训练剪枝框架OTO 神经网络剪枝原理_正则

 ,         

\frac{\partial L1(\gamma)}{\partial \gamma}=\left\{\begin{matrix} 1, & \gamma>0\\ 0,& \gamma=0\\ -1,&\gamma<0 \end{matrix}\right.

,这里的m.weight.grad.data.add_就是直接对梯度值进行计算,加上L1正则γ的梯度,也就是系数乘以相应的符号位。但通常情况来说,γ值绝大多数都是大于0的,这里在后面会介绍到

这是代码的链接


# ***********************稀疏训练(对BN层γ进行约束)**************************
def updateBN():
    for m in model.modules():
        if isinstance(m, nn.BatchNorm2d):
            if hasattr(m.weight, 'data'):
                m.weight.grad.data.add_(args.s * torch.sign(m.weight.data))  # L1正则


经过L1正则化训练以后,某些γ值趋于0,训练好模型以后,对所有γ值进行排序并确定裁剪比例,然后对那些γ值小于阈值的channel进行删除,得到裁剪以后的网络和权重。

l1 相比于 l2 为什么容易获得稀疏解? - amnesia的回答 - 知乎

Learning Efficient Convolutional Networks through Network Slimming

训练得到的resnet18网络的模型,正常训练的网络,这个没有使用L1正则对γ值进行调整,然后将所有的γ值拿出来并进行可视化,可以得到这样的图像

1、所有层γ值的可视化,这个是没有经过排序的

看得出来所有的γ值绝大多数都大于0,然后小于1

神经网络训练剪枝框架OTO 神经网络剪枝原理_深度学习_03

 2、所有层γ值的可视化,经过排序了的

神经网络训练剪枝框架OTO 神经网络剪枝原理_神经网络训练剪枝框架OTO_04

 γ值的直方图分布

神经网络训练剪枝框架OTO 神经网络剪枝原理_深度学习_05

 3、第3层γ值的可视化,未经过排序的

神经网络训练剪枝框架OTO 神经网络剪枝原理_神经网络训练剪枝框架OTO_06

4、γ值的可视化,经过排序了的

神经网络训练剪枝框架OTO 神经网络剪枝原理_深度学习_07


5、第18层γ值的可视化,未经过排序的

神经网络训练剪枝框架OTO 神经网络剪枝原理_正则_08

 6、第18层γ值的可视化,经过排序了的

神经网络训练剪枝框架OTO 神经网络剪枝原理_正则_09

 通常情况来说,γ值绝大多数都是大于0的,只有很少部分的值小于0