模型量化基础:FP32到INT8的转换原理
聊到端侧推理,量化是绕不开的话题。我刚开始接触端侧部署时,第一反应是“精度会不会掉得很惨?”后来踩过几次坑才发现,量化做得好,模型在手机上跑得又快又准。今天咱们就聊聊量化的核心——FP32到INT8的转换。
为什么非要做量化?
说白了,FP32的模型在服务器上跑没问题,但放到手机、IoT设备上就吃力了。你想想看,一个ResNet-50的FP32模型大概100MB,内存带宽和计算量都大。INT8模型能压缩到25MB左右,推理速度能快2-4倍。我在项目中遇到过,一个检测模型量化后,在骁龙855上从30fps直接飙到80fps,效果立竿见影。
量化核心收益:
- 模型体积缩小4倍(FP32→INT8)
- 推理速度提升2-4倍
- 内存带宽降低75%
- 功耗显著下降
FP32到INT8的转换原理
量化本质上是个映射过程。FP32的取值范围大约是[-3.4e38, 3.4e38],而INT8只有[-128, 127](有符号)或[0, 255](无符号)。我们需要找到一个映射函数,把FP32的值“塞”进INT8的范围内。
数学上,量化公式很简单:
Q = round(R / S) + Z
其中:
- R:原始的FP32值
- Q:量化后的INT8值
- S:缩放因子(scale),FP32的一个步长对应多少INT8
- Z:零点偏移(zero point),FP32的0对应哪个INT8值
反量化就是逆过程:
R = (Q - Z) * S
嗯,这里要注意,round操作会引入量化误差。我刚开始做量化时,总想着把S算得特别精细,后来发现没必要——只要误差在可接受范围内,模型精度就不会崩。
对称量化 vs 非对称量化
这两种方式的核心区别在于:零点Z怎么处理。
对称量化
对称量化强制零点Z=0。也就是说,FP32的0映射到INT8的0。公式简化为:
Q = round(R / S)
它的特点是:
- 实现简单,计算量小
- 适合权重(weights)量化——权重通常关于0对称分布
- 但激活值(activations)往往不是对称的,比如ReLU后的值全是非负的
我个人的习惯是,权重用对称量化,激活值看情况。有一次我图省事,全用对称量化,结果一个MobileNet的精度掉了3个点,排查半天发现是激活值分布不对称导致的。
非对称量化
非对称量化允许Z不为0。它通过零点偏移,能更好地适配非对称分布的数据。公式就是最前面那个:
Q = round(R / S) + Z
它的特点是:
- 能覆盖更广的数据分布范围
- 适合激活值量化(比如ReLU后的[0, 6]范围)
- 计算稍微复杂一点,但现代硬件都支持
我的经验:对于卷积层的权重,用对称量化就够了。对于激活值,尤其是经过ReLU、sigmoid等非线性函数后,建议用非对称量化。我曾经在一个语义分割模型上试过,非对称量化比对称量化精度高了1.5个点。
量化参数的计算
量化参数S和Z怎么算?需要先确定FP32数据的范围[min, max]。
对于对称量化:
S = max(|min|, |max|) / 127
Z = 0
对于非对称量化:
S = (max - min) / 255
Z = round(-min / S)
这里有个坑:Z可能会超出[0, 255]范围。我曾经遇到过Z算出来是-3,直接导致量化结果全错了。所以一定要做clip操作:
Z = clip(round(-min / S), 0, 255)
避坑指南:我曾经在一个项目中,直接用整个数据集的min和max算量化参数,结果有个离群点把范围拉得特别大,导致量化精度惨不忍睹。后来改用百分位法(比如取1%和99%分位点),效果好了很多。
量化误差的来源
量化误差主要来自三个方面:
- 舍入误差:round操作导致的,不可避免但可控
- 截断误差:超出INT8范围的值被clip掉
- 精度损失:FP32的精细信息在INT8中丢失
你想想看,FP32有约23位有效数字,INT8只有8位,信息量差了3个数量级。但好在神经网络对噪声有一定鲁棒性,只要量化策略得当,精度损失可以控制在1%以内。
实际量化流程
我一般按这个步骤来:
- 收集统计数据:用校准数据集跑一遍模型,记录每层的激活值分布
- 计算量化参数:根据分布计算S和Z
- 量化权重:权重通常用对称量化,一次性搞定
- 量化激活值:激活值用非对称量化,注意处理边界
- 验证精度:跑一遍验证集,对比量化前后的精度
如果精度下降太多,我会调整校准数据集的大小,或者改用更精细的量化策略(比如每通道量化)。
知识体系图
下面这张图总结了量化的核心逻辑,从FP32到INT8的转换路径,以及对称/非对称量化的选择依据。
总结一下
量化不是玄学,核心就是找到合适的S和Z,把FP32映射到INT8。对称量化简单高效,适合权重;非对称量化灵活精准,适合激活值。实际项目中,我建议先用对称量化试试权重,再根据激活值分布决定是否用非对称量化。校准数据集的选择也很关键,别让离群点毁了你的量化精度。