最开始关注这个工程是因为看到有人用YOLOv3进行模型剪枝后参数量减少80%,Flops降低70%,mAP反而还提升了,github链接:https://github.com/Lam1360/YOLOv3-model-pruning,是在ICCV2017的Learning Efficient Convolutional Networks through Network Slimming基础上实现的,原版github链接:https://github.com/foolwood/pytorch-slimming。因为通道剪枝实现简单,效果也还不错,目前在工业界应用的最为广泛。
Introduction
主要提到CNN网络部署的三个难题:模型大小、运行时间占用内存、计算量。
Related Work
文中探讨了其他5种方法的优缺点。
- 低秩分解。“Exploiting linear structure within convolutional networks for efficient evaluation”用SVD分解这样的低秩分解技术在全连接层表现比较好,可以将模型压缩3倍,但无明显速度提升,因为主要计算量来自卷积层。
- 权重量化。“Compressing neural networks with the hashing trick”通过量化网络权重,只需存储共享权重和哈希索引,节省存储空间,但不能节省运行内存和推理时间。“Imagenet classification using binary convolutional neural networks” 和“Training deep neural networks with weights and activations constrained to+1 or-1”将权值量化为二值/三值,极大压缩模型大小,提升速度,但精度损失大。
- 权重剪枝/稀疏化。“Learning both weights and connections for efficient neural network”和“Training sparse neural networks”剪枝掉不重要的连接,使权重稀疏化,但还是占用运行内存,激活值上密集的。
- 结构剪枝/稀疏化。结构剪枝是对网络结构的(channels,neurons等)一部分做剪枝或稀疏化,而不是对个别权重,因此不太需要特别的库来实现推理加速和运行时的内存节省。本文的通道剪枝也是属于结构剪枝。
- 神经结构学习。用强化学习学习网络结构,很高效。
Network slimming
论文中对每一个通道引入一个缩放因子,与通道的输出相乘。接着联合训练网络权重和这些缩放因子,最后将小缩放因子的通道直接剪除,微调剪枝后的网络。
而论文采用L1正则化施加到BN层的缩放因子gamma上的方法,即认为gamma越接近0,对应的输出对结果的重要性就很低,开源代码实现如下:
# additional subgradient descent on the sparsity-induced penalty term
def updateBN():
for m in model.modules():
if isinstance(m, nn.BatchNorm2d):
m.weight.grad.data.add_(args.s*torch.sign(m.weight.data)) # L1
引入缩放因子正则项之后,得到模型的很多缩放因子正则项都会趋于0。对缩放因子的绝对值排序后,减去对应剪枝百分比的通道,再进行finetune,重复进行网络瘦身的就能得到紧凑的小网络了。
这种剪枝方法在应对ResNet和DenseNet这类跨层连接的网络不太好,因为每一层的输出会作为后续多个层的输入,且其BN是在卷积之前做的。在这种情况下,稀疏化是在层的输入末端得到的,一个层选择性的接受所有通道的子集去做下一步的卷积运算。为了在测试时节省参数和计算量,我们需要放置一个通道选择层鉴别出重要的通道。
Experiment
码字不易,看完记得点赞哦~