4、训练后量化(PTQ):校准数据集、KL散度与熵校准、PTQ vs QAT 对比
训练后量化,简称 PTQ,是我在实际项目中用得最多的压缩手段。原因很简单——不需要重新训练模型,拿一个已经训好的浮点模型,跑几步校准流程,就能直接转成 INT8 甚至 INT4。说白了,这是性价比最高的量化方案。
但 PTQ 也不是无脑就能用的。你想想看,模型在 FP32 下学到的分布,硬生生压缩到 256 个离散值,信息损失是必然的。关键就在于怎么让这个损失最小化。今天我们就从校准数据集、KL 散度校准,再到 PTQ 和 QAT 的选型对比,把这块彻底讲透。
4.1 校准数据集:PTQ 的“标尺”
PTQ 的第一步,是准备一个校准数据集。这个数据集不需要很大,但必须能代表真实推理时的数据分布。我见过不少新手直接拿训练集做校准,结果量化后的模型在线上表现很差——因为训练集和真实场景的分布有偏差。
校准数据集的核心要求:
- 代表性:覆盖真实推理场景中的典型输入
- 多样性:包含边缘情况,比如极端亮度、噪声、遮挡等
- 规模适中:通常 100~500 张图片或 1000~5000 个样本就够
校准数据集的作用,是让量化器“看到”激活值的真实分布。量化器会跑一遍前向推理,收集每一层的激活值统计量——最小值、最大值、均值、方差,然后根据这些统计量去计算量化参数(scale 和 zero-point)。
举个例子,我用 TensorRT 做 PTQ 时,校准数据集一般选 200 张验证集图片。如果任务是人脸检测,我会确保这 200 张里包含不同光照、不同角度、不同肤色的人脸。嗯,这里要注意:千万别用训练集做校准,否则量化参数会过拟合到训练分布上。
我的经验:校准数据集的质量,直接决定 PTQ 的精度。如果校准集和线上数据分布偏差超过 5%,量化后的精度可能掉 2~3 个点。我建议每次上线前,先用一小段线上日志数据做校准集验证。
4.2 KL 散度与熵校准:找到最优截断阈值
校准数据集准备好了,接下来就是核心问题:怎么确定量化范围?
对于对称量化(比如 INT8,范围 [-128, 127]),我们需要决定一个截断阈值 T。所有值大于 T 的值都会被截断到 ±T,然后映射到 INT8 范围。T 选大了,量化精度低(因为步长大);T 选小了,截断误差大(因为很多值被硬截断)。
KL 散度校准法,就是用来解决这个问题的。它的核心思想是:找一个阈值 T,使得量化后的分布和原始 FP32 分布的 KL 散度最小。
KL 散度衡量的是两个分布之间的差异。公式长这样:
D_KL(P || Q) = Σ P(i) * log(P(i) / Q(i))
其中 P 是原始 FP32 激活值的分布,Q 是量化后再反量化回来的分布。我们遍历所有可能的 T,计算每个 T 下的 KL 散度,选最小的那个。
具体流程是这样的:
- 收集某一层所有激活值,统计直方图(比如 2048 个 bin)
- 从某个候选阈值开始,截断直方图右侧的 bin
- 将截断后的分布归一化,得到 P
- 将 P 量化到 INT8 范围,再反量化回 FP32,得到 Q
- 计算 D_KL(P || Q)
- 遍历所有候选阈值,选 KL 散度最小的那个
我在项目中遇到过一个问题:KL 散度校准对某些层效果很好,但对某些层反而更差。后来发现,那些层激活值的分布是双峰的,KL 散度在这种分布上容易找到局部最优。解决办法是:对这类层单独用 MSE 校准,或者直接跳过校准用默认阈值。
避坑指南:KL 散度校准不是万能的。如果你的模型激活值分布特别宽(比如有 outlier),KL 散度可能会选一个偏大的阈值,导致量化精度下降。我曾经在一个 NLP 模型上踩过这个坑,最后改用百分位法(比如 99.9% 分位)才解决问题。
4.3 PTQ vs QAT:选型对比
PTQ 和 QAT 是量化的两条路。很多同学问我:到底该用哪个?我的回答是:看你的精度要求和工程成本。
下面这张表是我自己整理的对比,你可以直接拿去用:
| 对比维度 | PTQ(训练后量化) | QAT(量化感知训练) |
|---|---|---|
| 是否需要训练 | 不需要,直接量化 | 需要,在训练中模拟量化 |
| 精度损失 | 通常 1~3% | 通常 <1% |
| 工程成本 | 低,几小时搞定 | 高,需要训练数据和 GPU 资源 |
| 适用场景 | 快速部署、模型已训好、精度要求不高 | 精度敏感、模型可重新训练、有充足资源 |
| 校准数据需求 | 需要少量校准集 | 需要完整训练集 |
| 对硬件适配 | 依赖校准算法 | 依赖训练框架的量化模拟 |
我个人习惯是:先跑 PTQ,看精度能不能接受。如果精度掉得太多,再考虑 QAT。毕竟 PTQ 的成本低得多,而且大部分场景下精度损失都在可接受范围内。
举个例子,我之前做一个目标检测模型,FP32 的 mAP 是 72.5%。PTQ 后掉到 70.8%,损失 1.7 个点。业务方说可以接受,那就直接上线了。如果业务方要求必须 72% 以上,那我才会启动 QAT 流程。
但有一种情况我建议直接上 QAT:模型本身很小,比如 MobileNet 系列。小模型对量化误差更敏感,PTQ 可能掉 5~8 个点,QAT 能控制在 1~2 个点内。
选型建议:
- 大模型(ResNet、BERT 等):优先 PTQ,精度损失可控
- 小模型(MobileNet、SqueezeNet 等):建议 QAT,否则精度损失太大
- 精度敏感场景(医疗、自动驾驶):直接 QAT,别省那点成本
- 快速迭代场景(A/B 测试、Demo):PTQ 足够
4.4 PTQ 完整流程与知识图谱
下面这张图是我画的 PTQ 核心流程,从校准数据集到最终量化模型,每一步都标清楚了:
从图上你能看到,PTQ 的流程是线性的:校准数据集 → 前向推理收集统计 → KL 散度校准 → 计算量化参数 → 输出量化模型。每一步都有明确的输入输出,这也是 PTQ 工程化友好的原因。
最后说一句:PTQ 不是银弹,但它是你量化工具箱里最趁手的那把。掌握好校准数据集的选择和 KL 散度的原理,大部分场景都能搞定。如果精度实在扛不住,再上 QAT 也不迟。