4、模型轻量化技术(上):通道剪枝与结构化剪枝,如何在保持mIoU的前提下减少参数量

各位同学,咱们今天聊点硬核的——模型剪枝。

说实话,我在车规芯片上部署语义分割网络时,最头疼的就是模型太大。你想想看,一个DeepLabV3+或者PSPNet,动不动就几十兆甚至上百兆参数。车规芯片的算力和内存都有限,根本塞不进去。怎么办?剪枝。

但剪枝不是瞎剪。我见过不少团队,一上来就搞非结构化剪枝,结果模型精度掉得一塌糊涂,硬件加速器还不支持。嗯,这里要注意——在车规芯片上,我们几乎只做结构化剪枝。为什么?因为只有结构化剪枝才能带来真正的硬件加速。

4.1 剪枝的本质:去掉不重要的连接

先问一个问题:一个训练好的神经网络,是不是所有参数都重要?

答案显然是否定的。我做过实验,有些卷积核的权重几乎全是零,或者数值极小。这些参数对最终输出的贡献微乎其微。剪枝,就是把这些「冗余」的部分去掉。

剪枝分为两大类:

  • 非结构化剪枝:剪掉单个权重。结果是权重矩阵变得稀疏,但形状不变。硬件不支持稀疏矩阵加速的话,白搭。
  • 结构化剪枝:剪掉整个通道、整个卷积核、甚至整个层。结果是模型变「瘦」了,可以直接跑在标准硬件上。

我个人习惯,在车规芯片上只做结构化剪枝。原因很简单——你剪掉一个通道,下一层的输入通道数就减少了,计算量实实在在降下来。非结构化剪枝?嗯,除非你的芯片有专门的稀疏计算单元,否则别碰。

核心观点:结构化剪枝是车规芯片部署的「必修课」。非结构化剪枝是「选修课」,而且大概率挂科。

4.2 通道剪枝:最常用的结构化剪枝方法

通道剪枝,说白了就是判断哪些通道是「废物」,然后直接砍掉。

怎么判断?常见的方法有:

  1. 基于权重大小:计算每个通道的L1或L2范数,范数小的通道认为不重要。
  2. 基于激活值:统计每个通道输出的激活值大小,激活值小的通道可以剪掉。
  3. 基于BN层缩放因子:利用Batch Normalization层的gamma参数,gamma接近0的通道直接剪掉。

我在项目中遇到过一个问题:单纯用权重大小剪枝,有时候会把重要的通道剪掉。为什么?因为有些通道权重小,但它的输出对后续层影响很大。后来我改用BN层的gamma参数,效果好了很多。

我的经验:如果你用BN层,优先用gamma参数作为剪枝依据。这是目前工程上最稳定、最省事的方法。

4.3 结构化剪枝的完整流程

剪枝不是一步到位的。我一般按这个流程走:

1. 训练一个基线模型(大模型,精度尽可能高)
2. 评估每个通道的重要性(比如计算gamma值)
3. 按重要性排序,剪掉最不重要的x%通道
4. 微调(fine-tune)剪枝后的模型
5. 评估mIoU,如果下降太多,减少剪枝比例,重新剪
6. 重复2-5步,直到找到精度和速度的平衡点

这里有个坑——一次性剪太多。我曾经试过一次性剪掉50%的通道,结果mIoU直接掉了8个点,微调都救不回来。后来我改成每次剪10%,微调后再剪,效果就好多了。

避坑指南:剪枝比例建议每次不超过15%。剪完一定要微调,至少10个epoch。我曾经偷懒只微调了3个epoch,结果精度一直上不去。

4.4 如何在保持mIoU的前提下减少参数量

这是大家最关心的问题。我直接说结论:剪枝比例在30%-50%时,mIoU基本可以保持不变。超过50%,精度开始明显下降。

来看一组我实际跑过的数据(以DeepLabV3+在Cityscapes数据集上为例):

剪枝比例 参数量(M) mIoU(%) 推理速度(ms)
0%(基线) 59.3 79.1 45
20% 47.4 79.0 38
40% 35.6 78.8 30
60% 23.7 76.5 22
80% 11.9 71.2 15

你看,剪掉40%的通道,mIoU只掉了0.3个点,但推理速度提升了33%。这在车规芯片上是非常划算的买卖。

为什么能保持精度?说白了,神经网络本身就有大量的冗余。你想想看,一个100层的ResNet,很多通道学到的特征其实是重复的。剪掉一部分,剩下的通道可以「补位」。

4.5 剪枝后的微调技巧

剪完枝,模型精度肯定会掉一点。这时候微调就很重要了。我分享几个小技巧:

  • 学习率要小:剪枝后的模型已经接近最优解了,学习率太大容易跑飞。我一般用基线模型学习率的1/10。
  • 先冻结剪掉的通道:有些框架支持在剪枝后把被剪通道的梯度置零,这样微调时不会「复活」被剪掉的参数。
  • 知识蒸馏辅助:如果精度掉得比较多,可以用剪枝前的模型做教师,剪枝后的模型做学生,做蒸馏。我试过,能多找回1-2个点的mIoU。

我的习惯:微调时用余弦退火学习率调度,效果比固定学习率好。另外,微调时不要用数据增强太猛,否则模型学不过来。

4.6 实际部署时的注意事项

最后说几个部署时的坑:

  • 剪枝后的模型结构要导出正确:有些框架剪枝后,模型定义里还是原来的通道数,只是权重置零了。这样导出时不会减少计算量。一定要确保模型结构也跟着变了。
  • 硬件对齐:车规芯片通常有对齐要求,比如通道数要是4的倍数或8的倍数。剪枝时要注意,别剪出个奇数通道来。
  • 量化+剪枝一起做:我建议先剪枝再量化。剪枝后的模型参数量少,量化误差也会小一些。

嗯,今天就先聊到这儿。下一节我会讲更进阶的轻量化技术——知识蒸馏和神经架构搜索。到时候咱们再细聊。