4. 模型量化原理与精度分析
量化,说白了就是把模型从「养尊处优」的浮点数世界,拽到「精打细算」的整数世界。你想想看,FP32 一个数占 4 个字节,INT8 只占 1 个字节,这一下子内存带宽就省了 75%。在 NPU 上跑推理,内存搬运往往是瓶颈,量化就是最直接的加速手段。
我刚开始做嵌入式部署时,总觉得量化是「玄学」——明明在 PC 上跑得好好的,一量化到 INT8,检测框就飘了。后来踩的坑多了,才慢慢摸清里面的门道。这一章,我就把量化原理和精度调优的经验掰开揉碎讲给你听。
4.1 量化基础:FP32 / FP16 / INT8
先看一张表,把三种精度的核心参数说清楚:
| 精度类型 | 位宽 | 表示范围 | 相对 FP32 加速比 | 典型场景 |
|---|---|---|---|---|
| FP32 | 32 bit | ±3.4×10³⁸ | 1× | 训练、高精度推理 |
| FP16 | 16 bit | ±6.5×10⁴ | ~2× | GPU/部分 NPU 推理 |
| INT8 | 8 bit | [-128, 127] | ~4× | NPU 端侧推理 |
FP16 其实是个「折中方案」。我记得在某个项目里,NPU 原生支持 FP16 计算,但内存带宽还是吃紧。换成 INT8 后,推理帧率直接从 15 FPS 飙到了 45 FPS,代价是 mAP 掉了 0.8%。这个 trade-off 值不值?得看你的业务场景。
核心结论:INT8 量化是 NPU 部署的「标配」。FP16 适合精度敏感但带宽不敏感的场景,FP32 在端侧基本不用。
4.2 对称量化与非对称量化
量化的本质,就是找一个映射关系,把浮点数 r 映射到整数 q。公式很简单:
r = S × (q - Z)
其中 S 是缩放因子,Z 是零点偏移。这两个参数怎么定,就引出了两种主流方案。
对称量化
零点 Z = 0,映射关于原点对称。适合权重这种正负分布均匀的数据。
r = S × q
非对称量化
零点 Z ≠ 0,可以偏移。适合激活值这种往往非负(比如 ReLU 之后)的数据。
r = S × (q - Z)
我个人的习惯是:权重用对称,激活用非对称。为什么?权重经过训练后大致是零均值的,对称量化不会浪费表示范围;激活值很多是正数,非对称量化能把整个 INT8 的 [-128, 127] 都用上,精度损失更小。
避坑指南:我曾经在一个项目中,对 ReLU 后的激活值用了对称量化,结果精度掉了 2%。换成非对称后,精度损失降到了 0.3%。原因很简单——对称量化把一半的表示范围浪费在了负数上。
4.3 校准数据集与 KL 散度
量化参数 S 和 Z 怎么算?不是拍脑袋定的,得靠「校准」。校准的核心是:找一个阈值,让量化前后的信息损失最小。
这里就要请出 KL 散度了。KL 散度衡量的是两个分布之间的差异:
D_KL(P || Q) = Σ P(i) × log(P(i) / Q(i))
在校准过程中,我们拿一小部分训练数据(通常 500~1000 张图)跑一遍 FP32 推理,统计出激活值的直方图 P。然后尝试不同的截断阈值 T,把 P 量化再反量化得到 Q,计算 D_KL(P || Q)。选让 KL 散度最小的那个 T。
校准数据集的选择很有讲究。我见过有人随便拿 100 张图做校准,结果量化后的模型在复杂场景下直接崩了。为什么?校准集没有覆盖到激活值的极端情况。
注意:校准数据集必须代表真实推理场景的数据分布。如果训练集有 10 万张图,校准集至少选 500 张,且要包含光照变化、目标尺度变化等多样性。
4.4 量化精度损失分析与调优
量化一定会掉精度,关键是怎么把损失控制在可接受范围内。我总结了一套「三步走」的调优流程:
- 定位敏感层:逐层对比 FP32 和 INT8 的输出,找出误差最大的层。
- 分析误差来源:是权重分布太宽?还是激活值有离群点?
- 针对性修复:对敏感层做混合精度(保留 FP16),或者调整校准策略。
下面这张图,是我在实际项目中总结的量化精度调优流程:
在实际调优中,有几个「坑」我反复踩过:
- 离群点问题:激活值里偶尔出现几个很大的数,会把整个量化范围撑宽,导致大部分值精度损失。解决办法是「截断」,把 99.9% 分位以外的值直接砍掉。
- BN 层融合:量化前一定要把 BN 层融合进 Conv 层,否则精度会莫名其妙地掉。我见过有人忘了这步,折腾了两天。
- 逐通道量化:对卷积权重,逐通道量化比逐层量化精度高 0.5%~1%。代价是计算量稍微大一点,但 NPU 通常都支持。
经验之谈:量化后的模型精度如果掉了超过 1%,先别急着调参。检查一下校准集是不是有问题,或者有没有层被「漏量化」了。我遇到过最离谱的一次,是某个自定义算子没注册量化规则,整个模型精度直接崩到 0。
最后说一句,量化不是「一键优化」的魔法。它需要你对模型结构、数据分布、NPU 硬件特性都有深入理解。但一旦调好了,那种在嵌入式设备上跑出实时检测的成就感,嗯,值得。