第4章:模型量化原理:FP32到INT8的转换
说到模型量化,很多嵌入式工程师第一反应就是「精度会掉」。嗯,这个想法没错,但也不全对。我刚开始接触BEV模型部署时,也觉得量化就是把高精度数砍成低精度数,肯定损失很大。直到我在一个ADAS项目里,硬是把一个FP32的BEV模型压到INT8,精度只掉了0.3%,推理速度却快了4倍。那一刻我才真正理解——量化不是简单的「砍数」,而是一门平衡艺术。
4.1 为什么非要从FP32转到INT8?
先说说为什么我们要折腾这个。FP32,也就是32位浮点数,每个数占4个字节。INT8呢?只占1个字节。你想想看,模型参数直接压缩到原来的四分之一。在嵌入式设备上,内存带宽往往是最大的瓶颈。我做过一个统计:在Jetson Orin上,FP32的BEV模型推理一次要450ms,其中数据搬运占了将近300ms。换成INT8后,推理时间直接降到120ms。
说白了,量化就是用更少的比特去表示一个数值范围。FP32能表示约10^38种数值,而INT8只能表示256种。关键问题来了——怎么用256个数去近似表达原来那海量的数值?
4.2 对称量化 vs 非对称量化
这里有两个主流方案:对称量化和非对称量化。我分别讲讲它们的原理和适用场景。
4.2.1 对称量化
对称量化的核心思想很简单:把浮点数的零点映射到INT8的零点。也就是说,浮点数的0在量化后还是0。它的映射公式是:
Q = round(S * F)
其中:
Q:量化后的INT8值
F:原始FP32值
S:缩放因子(scale)
反量化公式就是:
F = Q / S
这里S怎么算?S = 127 / max(|F_max|, |F_min|)。说白了,就是用整个浮点数的最大值去决定缩放比例。
我个人的经验:对称量化特别适合权重(weights)的量化。为什么?因为训练好的模型权重通常分布比较对称,正负值差不多。我在量化一个BEV的backbone网络时,用对称量化权重的精度损失只有0.1%。
4.2.2 非对称量化
非对称量化就灵活多了。它允许浮点数的零点映射到INT8的非零点。公式变成:
Q = round(S * (F - Z))
其中:
Z:零点偏移(zero point)
反量化:
F = Q / S + Z
这里S = (Q_max - Q_min) / (F_max - F_min),Z = Q_min - S * F_min。
避坑指南:我曾经在量化BEV模型的注意力层时,发现对称量化后精度掉了2%。换成非对称量化后,精度只掉了0.5%。为什么?因为注意力层的输出分布往往是不对称的,很多值集中在正半轴。这时候非对称量化能更好地利用INT8的256个档位。
| 对比项 | 对称量化 | 非对称量化 |
|---|---|---|
| 零点映射 | 浮点0 → INT8 0 | 浮点0 → INT8 任意值 |
| 计算复杂度 | 低(不需要零点偏移计算) | 高(需要处理零点偏移) |
| 适用场景 | 权重、分布对称的激活值 | 分布不对称的激活值 |
| 硬件支持 | 大多数硬件原生支持 | 部分硬件需要额外处理 |
| 精度表现 | 对称分布时优秀 | 非对称分布时更优 |
4.3 校准数据集的选择
校准数据集,说白了就是用来确定量化参数(S和Z)的样本。这一步非常关键,我见过太多人随便拿几张图就跑量化,结果模型直接崩了。
4.3.1 校准数据集应该多大?
我的经验是:100-500张图片就够了。别贪多,也别太少。我记得有一次用1000张图片做校准,结果跟用200张的效果差不多,白白浪费了计算时间。
4.3.2 数据分布要覆盖全面
校准数据集必须能代表实际部署场景的数据分布。比如你的BEV模型要处理白天、夜晚、雨天、隧道等各种场景,那校准数据里这些场景都得有。我曾经犯过一个错误:只用白天场景的数据做校准,结果模型在夜晚场景下精度掉了5%。
警告:千万不要用训练集做校准!训练集的数据分布跟实际部署场景往往有偏差。我建议从验证集中随机抽取一部分作为校准集,这样更接近真实场景。
4.3.3 校准方法的选择
常见的校准方法有几种:
- MinMax:直接取所有校准数据的最大值和最小值。简单粗暴,但对异常值敏感。
- Percentile:取某个百分位数(比如99.9%)作为最大值。能过滤掉异常值。
- KL散度:通过最小化量化前后分布的KL散度来确定阈值。精度通常最好,但计算量大。
- MSE:最小化量化前后的均方误差。也是个不错的选择。
我个人习惯用KL散度做校准。虽然慢一点,但精度确实有保障。在BEV模型的检测头上,KL散度比MinMax高了0.8%的mAP。
4.4 量化后的精度验证
量化完不是就完事了。一定要做精度验证。我一般会跑三个指标:
- 整体mAP对比:量化前后mAP下降不超过1%算合格。
- 逐层误差分析:找出哪些层量化后误差最大,考虑对这些层保留FP32。
- 极端场景测试:专门挑一些难样本(比如遮挡严重、光照极差)来测试。
我的一个实用技巧:如果量化后精度下降太多,不要急着调校准参数。先检查一下模型里有没有数值范围特别大的层。我遇到过BEV模型的transformer层输出范围从-100到+100,直接量化肯定崩。这时候可以对这些层做逐层量化,或者用混合精度方案。
4.5 实战中的量化流程
最后,我总结一下在实际项目中做量化的标准流程:
1. 准备校准数据集(100-500张,覆盖全场景)
2. 选择量化方案(权重用对称,激活值用非对称)
3. 运行校准,确定S和Z
4. 量化模型,保存INT8权重
5. 在验证集上跑精度对比
6. 如果精度下降超过1%,做逐层分析
7. 对误差大的层做混合精度(FP32+INT8)
8. 重复步骤5-7直到精度达标
嗯,量化这件事,说白了就是「用最小的代价换取最大的加速」。你只要掌握了原理,多跑几次实验,很快就能找到最适合自己模型的量化方案。下一章我会讲讲量化后的模型在嵌入式设备上如何做推理加速,到时候咱们再细聊。