4、模型轻量化技术:模型剪枝原理与实践、权重量化(INT8/FP16)、知识蒸馏入门、轻量化网络结构(MobileNet、ShuffleNet)

好,咱们进入第四章。这一章,我打算聊聊模型轻量化。

你想想看,一个ResNet-152跑在服务器上,显存占几个G,推理一次几十毫秒,这都没问题。但要是把它塞进一个只有2MB内存、主频1GHz的摄像头模组里呢?直接卡死。所以,轻量化不是可选项,是必选项。

我个人习惯把轻量化技术分成四类:剪枝、量化、蒸馏、以及直接设计轻量网络。咱们一个一个来。

4.1 模型剪枝:给网络“瘦身”

剪枝,说白了就是去掉那些不重要的连接或通道。神经网络里有很多参数,其实贡献很小。去掉它们,模型变小,速度变快,精度损失却不大。

剪枝分两种:非结构化剪枝和结构化剪枝。

  • 非结构化剪枝:把单个权重置为0。优点是压缩率高,但依赖稀疏计算库,硬件加速效果一般。我在项目中试过,实际推理速度提升有限,因为CPU和GPU对稀疏矩阵的支持并不完美。
  • 结构化剪枝:直接剪掉整个通道或卷积核。这是工业界的主流做法。剪完后模型结构变“瘦”,不需要特殊硬件支持,直接跑就快。

核心原则:剪枝不是乱剪。通常按“L1范数”或“L2范数”对卷积核排序,值小的优先剪掉。每次剪一点,然后微调恢复精度,再剪一点。这叫“迭代式剪枝”。

我曾经在一个行人检测项目里,把MobileNetV2的通道数剪掉30%,精度只掉了0.5%,但推理速度提升了近40%。嗯,这里要注意:剪枝比例超过50%后,精度会断崖式下跌。所以别贪心。

4.2 权重量化:用更少的比特表示参数

量化,就是把模型参数从32位浮点数(FP32)变成更低位宽的表示。最常见的是INT8和FP16。

为什么能这么做?因为神经网络对噪声有一定容忍度。你想想看,人眼看一张图,差几个像素值根本看不出来。网络也一样。

量化类型 位宽 模型体积缩小 推理加速 精度损失
FP32(基准) 32 bit 1x 1x
FP16 16 bit 约2x 1.5-2x 几乎无
INT8 8 bit 约4x 2-4x 0.5-2%

我个人建议:如果边缘设备支持FP16(比如NVIDIA Jetson系列),优先用FP16。精度几乎无损,部署最简单。如果设备只支持INT8(比如大部分手机NPU、树莓派的某些加速棒),那就得做INT8量化。

避坑指南:我曾经在量化一个语义分割模型时,发现输出结果全是黑的。排查了半天,原来是激活值的分布太集中,量化时信息全丢了。解决办法是:先做“校准”,用一小批真实数据跑一遍,统计出激活值的min/max,再去做量化。很多框架(如TensorRT、ONNX Runtime)都支持这个功能。

4.3 知识蒸馏:大模型教小模型

知识蒸馏,说白了就是“师生学习”。用一个大的、精度高的教师模型,去指导一个小的、轻量的学生模型学习。

怎么教?不是直接让学生模仿教师的最终输出,而是模仿“软标签”。

  • 硬标签:类别概率,比如[0, 1, 0]。
  • 软标签:教师模型输出的概率分布,比如[0.1, 0.8, 0.1]。这里面包含了教师对“相似类别”的理解。

蒸馏的损失函数通常是:L = α * 硬标签损失 + (1-α) * 软标签损失。其中软标签损失用的是KL散度。

我记得有一次,我需要把一个YOLOv5s(小模型)部署到一款低端芯片上。直接训练,mAP只有68%。后来我用YOLOv5m(中等模型)做教师,蒸馏训练学生,mAP直接提到了72%。效果很明显。

注意:蒸馏不是万能的。如果教师模型本身就不准,那教出来的学生也好不到哪去。另外,学生模型的结构不能太“弱”,否则学不动。我一般建议学生模型的参数量至少是教师的1/10以上。

4.4 轻量化网络结构:MobileNet 与 ShuffleNet

前面说的剪枝、量化、蒸馏,都是对现有模型做“改造”。但如果你从零开始设计,为什么不直接用轻量化的网络结构呢?

这里我重点讲两个:MobileNet 和 ShuffleNet。

4.4.1 MobileNet:深度可分离卷积

MobileNet的核心思想,是把标准卷积拆成两步:

  1. 深度卷积:每个通道单独做卷积,不跨通道。
  2. 逐点卷积:用1x1卷积把通道信息融合起来。

这样做的好处是:计算量大幅下降。标准卷积的计算量是 K*K*C_in*C_out*H*W,而深度可分离卷积是 K*K*C_in*H*W + C_in*C_out*H*W。当K=3时,计算量大约只有原来的1/8到1/9。

MobileNetV2还引入了“倒残差结构”和“线性瓶颈”,进一步提升了效率。V3则加入了NAS(神经架构搜索)来寻找最优结构。

4.4.2 ShuffleNet:通道混洗

ShuffleNet的思路更巧妙。它用分组卷积来减少计算量,但分组卷积有个问题:不同组之间信息不流通。怎么办?

ShuffleNet提出“通道混洗”操作。就是把不同组的通道打乱重排,让信息在组间流动。你想想看,这就像洗牌一样,把不同花色的牌混在一起。

ShuffleNetV2更进一步,提出了四条实用准则:

  • 输入输出通道数相等时,内存访问成本最低。
  • 过多的分组卷积会增加内存访问。
  • 网络碎片化(多分支)会降低并行度。
  • 逐元素操作(如ReLU、Add)虽然计算量小,但内存访问成本不可忽视。

我的选择建议:如果设备对内存带宽敏感(比如很多嵌入式芯片),优先考虑ShuffleNetV2。如果设备有较好的GPU或NPU加速,MobileNetV3通常表现更好。我在一个智能门锁项目里,用ShuffleNetV2做人脸检测,在1.2GHz的Cortex-A7上跑到了30fps,效果很满意。

好了,这一章的内容就这些。总结一下:剪枝去掉冗余,量化压缩位宽,蒸馏传承知识,轻量网络从源头优化。四者可以组合使用,比如先剪枝再量化,或者用蒸馏训练一个轻量网络。具体怎么选,取决于你的硬件和精度要求。