3. 模型量化基础:FP32、FP16、INT8、INT4精度对比与量化原理

模型量化,说白了就是把模型里那些又大又沉的浮点数,换成更轻巧的整数来算。我刚开始接触这玩意儿的时候,也觉得不就是精度换速度嘛,后来踩了几个坑才发现,里面的门道比想象中深得多。

这一章咱们就掰开揉碎,把量化的底裤扒干净。从精度对比到量化原理,再到误差分析,一条龙讲透。

3.1 精度格式对比:FP32、FP16、INT8、INT4

先看一张表,把几种主流精度格式的参数摆出来。你想想看,同样一个模型,用不同精度存,体积和速度差了多少。

精度格式 位宽 动态范围 相对体积 典型场景
FP32 32 bit ~3.4×10³⁸ 1× 训练、高精度推理
FP16 16 bit ~6.5×10⁴ 0.5× 混合精度训练、移动端推理
INT8 8 bit 256 0.25× 边缘设备、实时推理
INT4 4 bit 16 0.125× 极致压缩、低功耗场景

FP32 是基准,精度高但体积大。FP16 砍了一半位宽,动态范围缩了不少,但大部分语音模型还能扛住。INT8 和 INT4 就猛了,体积直接降到四分之一和八分之一,但动态范围也窄得可怜。

关键点:动态范围决定了你能表示的最大值和最小值跨度。FP32 能表示从 1.4×10⁻⁴⁵ 到 3.4×10³⁸ 的数,INT8 只能表示 -128 到 127。量化就是把 FP32 的广阔天地,硬塞进 INT8 的小盒子里。

我在项目中遇到过用 INT8 量化一个语音增强模型,结果在安静环境下效果还行,一到嘈杂环境就崩了。后来一查,是动态范围不够,把一些关键的噪声特征给截断了。嗯,这里要注意,不是所有模型都适合压到 INT8 甚至 INT4。

3.2 量化原理:对称量化与非对称量化

量化说白了就是找一个映射关系,把浮点数映射到整数上。这个映射分两种:对称量化和非对称量化。

3.2.1 对称量化

对称量化假设浮点数的分布是以零为中心的。映射公式很简单:

Q = round(S × F)
其中:
Q = 量化后的整数值
F = 原始浮点值
S = 缩放因子(scale)

反量化就是:

F = Q / S

对称量化的好处是零点就是 0,计算时不用额外处理。坏处是如果浮点数分布偏了,比如全是正数,那负数那半边的量化区间就浪费了。

我的习惯:做对称量化时,我会先看一眼权重和激活值的分布。如果分布明显不对称,我会考虑用非对称量化,否则量化误差会偏大。

3.2.2 非对称量化

非对称量化引入了零点偏移,公式稍微复杂一点:

Q = round(S × F + Z)
其中:
Z = 零点(zero point)

反量化:

F = (Q - Z) / S

非对称量化能更好地适配非对称分布的数据。比如 ReLU 之后的激活值全是非负的,用非对称量化就能把整个量化区间都利用起来。

我曾经在一个语音识别模型上做过对比:对称量化 INT8 的 WER(词错误率)上升了 2.3%,换成非对称量化后只上升了 0.7%。差别还是挺明显的。

3.3 量化误差分析

量化不是无损的,误差主要来自三个方面:

  • 截断误差:浮点数超出量化范围时被硬截断。比如 INT8 最大只能表示 127,一个 128.5 的浮点数进来,直接变成 127。
  • 舍入误差:量化时 round 操作带来的精度损失。比如 3.14159 量化到 INT8,可能变成 3。
  • 梯度误差:量化操作不可导,反向传播时梯度近似不准,影响训练。

避坑指南:我曾经在量化一个语音合成模型时,忽略了激活值的异常点。有个别帧的激活值飙到了 500 多,INT8 直接截断到 127,结果合成出来的语音全是爆音。后来加了异常值裁剪,才把问题解决。

量化误差的衡量指标,我常用两个:

  • MSE(均方误差):量化前后数值的平方误差均值。
  • SNR(信噪比):信号功率与噪声功率的比值,越高越好。

下面这张图展示了量化误差的来源和传播路径:

量化误差来源与传播路径 FP32 浮点值 量化:Q = round(S × F + Z) 截断误差 超出范围被硬截断 舍入误差 round 操作精度损失 梯度误差 量化不可导 INT8 量化值 三种误差叠加,最终影响模型精度。实际项目中,截断误差往往是最致命的。

3.4 量化误差的缓解策略

知道了误差来源,怎么缓解?我总结了几条实战经验:

  • 校准数据集:量化前用一小批真实数据跑一遍,统计激活值的分布,确定最佳的 S 和 Z。我习惯用 500-1000 条语音做校准。
  • 异常值裁剪:把分布两端 0.1% 的极端值裁剪掉,避免量化区间被少数异常点占据。
  • 逐通道量化:每个卷积核或每个神经元单独算 S 和 Z,比逐层量化更精细。代价是计算量稍大。
  • 量化感知训练(QAT):在训练过程中模拟量化操作,让模型自己学会适应量化误差。效果最好,但需要重新训练。

我的建议:如果时间紧,先用后训练量化(PTQ)试试。如果精度损失在 1% 以内,直接上 PTQ 就行。如果损失超过 2%,再考虑 QAT。别一上来就搞 QAT,太费时间。

量化不是银弹,但用好了确实能带来质的飞跃。我记得有一次把语音唤醒模型从 FP32 压到 INT8,体积从 50MB 降到 12.5MB,推理速度提升了 3 倍,精度只掉了 0.3%。嗯,这种成就感,干过的人都懂。