3、模型轻量化基础:模型剪枝、权重量化(INT8/FP16)、知识蒸馏的核心原理与适用场景
好,咱们进入第三讲。这一讲的内容,说白了就是回答一个问题:怎么把一个大模型塞进一个只有几百KB内存的MCU里?
我刚开始做嵌入式AI那会儿,踩过不少坑。最惨的一次,模型在PC上跑得飞起,一部署到STM32上,直接内存溢出。嗯,从那以后,我就老老实实研究模型轻量化了。
今天咱们聊三个最核心的技术:模型剪枝、权重量化、知识蒸馏。这三板斧,基本能解决90%的部署难题。
3.1 模型剪枝:砍掉没用的神经元
模型剪枝,顾名思义,就是把模型里那些“不干活”或者“干得少”的神经元给砍掉。你想想看,一个神经网络动辄几百万参数,但真正起作用的可能只有一小半。
3.1.1 核心原理
剪枝的核心思想很简单:评估每个参数的重要性,然后删掉不重要的。
怎么评估重要性?常见的方法有两种:
- 基于权重大小:权重绝对值越小,说明它对输出的影响越小,可以剪掉。这是最粗暴也最常用的方法。
- 基于梯度:看这个参数对损失函数的敏感度。敏感度低的,剪掉也不影响精度。
我个人习惯用第一种,简单有效。但要注意,剪枝不是一次性剪完,而是迭代式剪枝:剪一点,微调一下,再剪一点,再微调。这样模型才能慢慢适应。
关键点:剪枝后的模型结构变了,需要重新微调(Fine-tune)才能恢复精度。千万别指望剪完直接跑,那精度会掉得你怀疑人生。
3.1.2 适用场景
剪枝最适合那些参数冗余大的模型,比如VGG、ResNet这种大网络。对于MobileNet这种本来就轻量的模型,剪枝效果有限。
我在项目中遇到过,把一个ResNet-50剪掉40%的参数,精度只掉了0.5%。但推理速度提升了近一倍。嗯,这笔买卖很划算。
小技巧:剪枝时,建议先对全连接层下手,因为全连接层的参数占比最大,冗余也最多。卷积层可以少剪一点。
3.2 权重量化:用更少的比特表示权重
量化,说白了就是用低精度数据类型代替高精度数据类型。比如,把32位浮点数(FP32)变成8位整数(INT8)或者16位浮点数(FP16)。
为什么要这么做?因为内存带宽和计算速度。INT8的乘法比FP32快4倍,内存占用只有1/4。在低功耗设备上,这简直是救命稻草。
3.2.1 INT8量化
INT8量化,就是把FP32的权重映射到[-128, 127]这个整数区间。核心公式很简单:
// 量化公式
q = round(r / S) + Z
// 反量化公式
r = (q - Z) * S
其中:
r: 原始浮点值
q: 量化后的整数值
S: 缩放因子(scale)
Z: 零点偏移(zero point)
这里有个坑:S和Z怎么选? 我刚开始做的时候,直接取权重的最大值和最小值来算S,结果精度掉得一塌糊涂。后来才发现,应该用校准数据集来统计激活值的分布,然后选一个合适的S。
注意:INT8量化对激活值的分布很敏感。如果激活值分布不均匀,量化误差会很大。建议先用KL散度或者均方误差来评估一下量化误差。
3.2.2 FP16量化
FP16量化就简单多了。它本质上是半精度浮点数,直接截断FP32的低16位就行。精度损失很小,但内存占用减半。
我记得有一次,在树莓派上跑一个目标检测模型,用FP16量化后,推理速度提升了30%,精度几乎没变。嗯,这种好事不常有。
| 量化类型 | 内存占用 | 精度损失 | 速度提升 | 适用硬件 |
|---|---|---|---|---|
| FP32 | 1x | 无 | 1x | 所有硬件 |
| FP16 | 0.5x | 极小 | 1.5-2x | GPU、部分NPU |
| INT8 | 0.25x | 较小 | 3-4x | NPU、DSP、MCU |
3.2.3 适用场景
- INT8:适合MCU、DSP、NPU这类硬件。比如STM32、K210、RK3588的NPU。
- FP16:适合GPU、部分AI加速芯片。比如Jetson Nano、树莓派。
你想想看,如果你的设备只有1MB内存,模型却有4MB,那量化就是唯一的选择。
3.3 知识蒸馏:让学生模型学老师
知识蒸馏,这个比喻很形象:一个老师(大模型)教学生(小模型)。老师懂的很多,但学生只需要学会关键知识就行。
3.3.1 核心原理
传统的训练,是让模型直接学习标签(比如猫、狗)。但知识蒸馏不一样,它让学生模型学习老师模型的输出分布。
为什么这样更好?因为老师的输出分布包含了暗知识。比如,一张猫的图片,老师不仅输出“猫”的概率高,还输出“老虎”的概率比“狗”高。这种信息,标签里是没有的。
蒸馏的损失函数通常包含两部分:
Loss = α * 硬标签损失 + (1-α) * 软标签损失
其中:
- 硬标签损失:学生输出与真实标签的交叉熵
- 软标签损失:学生输出与老师输出的KL散度
- α:平衡系数,通常取0.7-0.9
这里有个关键参数:温度(Temperature)。温度越高,老师输出的分布越平滑,学生能学到的暗知识越多。但温度太高,分布就太平了,反而学不到东西。我一般取3-5。
经验之谈:蒸馏时,建议先用老师模型在训练集上跑一遍,把输出保存下来。这样训练学生模型时,就不用每次都跑老师了,能省不少时间。
3.3.2 适用场景
知识蒸馏最适合模型结构差异大的场景。比如,老师是ResNet-152,学生是MobileNet-V3。这种情况下,剪枝和量化都不太适用,但蒸馏效果很好。
我曾经在一个语音唤醒项目里,用蒸馏把模型从2MB压缩到200KB,精度只掉了1%。嗯,这招真的很管用。
总结一下:
- 模型剪枝:适合大模型,砍掉冗余参数。
- 权重量化:适合所有模型,用低精度换速度和内存。
- 知识蒸馏:适合模型结构差异大的场景,让小模型学大模型的知识。
这三招可以组合使用。比如,先剪枝,再量化,最后蒸馏。但要注意顺序:先剪枝再量化,因为剪枝会改变模型结构,量化是在固定结构上做的。
好了,这一讲就到这里。下一讲,咱们聊聊模型部署的实战流程,从训练到推理,一步步带你走一遍。