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(信噪比):信号功率与噪声功率的比值,越高越好。
下面这张图展示了量化误差的来源和传播路径:
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%。嗯,这种成就感,干过的人都懂。