第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 量化后的精度验证

量化完不是就完事了。一定要做精度验证。我一般会跑三个指标:

  1. 整体mAP对比:量化前后mAP下降不超过1%算合格。
  2. 逐层误差分析:找出哪些层量化后误差最大,考虑对这些层保留FP32。
  3. 极端场景测试:专门挑一些难样本(比如遮挡严重、光照极差)来测试。

我的一个实用技巧:如果量化后精度下降太多,不要急着调校准参数。先检查一下模型里有没有数值范围特别大的层。我遇到过BEV模型的transformer层输出范围从-100到+100,直接量化肯定崩。这时候可以对这些层做逐层量化,或者用混合精度方案。

4.5 实战中的量化流程

最后,我总结一下在实际项目中做量化的标准流程:

1. 准备校准数据集(100-500张,覆盖全场景)
2. 选择量化方案(权重用对称,激活值用非对称)
3. 运行校准,确定S和Z
4. 量化模型,保存INT8权重
5. 在验证集上跑精度对比
6. 如果精度下降超过1%,做逐层分析
7. 对误差大的层做混合精度(FP32+INT8)
8. 重复步骤5-7直到精度达标

嗯,量化这件事,说白了就是「用最小的代价换取最大的加速」。你只要掌握了原理,多跑几次实验,很快就能找到最适合自己模型的量化方案。下一章我会讲讲量化后的模型在嵌入式设备上如何做推理加速,到时候咱们再细聊。