4、训练后量化(PTQ):PTQ 原理、校准数据集、KL散度与MinMax校准方法
训练后量化,英文叫 Post-Training Quantization,简称 PTQ。说白了,就是模型训练完了,我们直接拿它来做量化。不需要重新训练,也不需要反向传播。这是目前工业界落地最广、门槛最低的量化方式。
我刚开始接触模型压缩时,第一个学的就是 PTQ。为什么?因为它快啊。你想想看,一个已经训好的模型,你花几个小时跑一遍校准,就能把 FP32 的权重和激活值压到 INT8,精度损失往往在 1% 以内。这在项目交付期简直是救命稻草。
4.1 PTQ 的核心原理
PTQ 的原理其实不复杂。我们有一组训练好的浮点参数,现在要把它映射到低比特整数空间。这个映射过程,核心就是找到合适的 缩放因子(scale) 和 零点(zero point)。
公式很简单:
Q = round( R / scale ) + zero_point
其中 R 是浮点值,Q 是量化后的整数值。scale 决定了每个量化步长代表多大的浮点范围,zero_point 则负责对齐浮点零和整数零。
但问题来了——scale 怎么选?选大了,精度损失大;选小了,容易溢出。这就是 PTQ 要解决的核心矛盾。
关键点:PTQ 的本质是在「量化误差」和「截断误差」之间找平衡。scale 越大,截断误差越小,但量化误差越大;scale 越小,量化误差越小,但截断误差越大。
4.2 校准数据集:你选对了吗?
PTQ 需要一小部分数据来做校准。这个数据集不需要很大,几百到几千张图片通常就够了。但这里有个坑——校准数据集必须能代表真实推理时的数据分布。
我在项目中遇到过一件事。有个同学拿 ImageNet 的验证集做校准,模型在公开测试集上精度很好。但一部署到客户现场,精度直接崩了。为什么?因为客户的数据是监控摄像头拍的,光照、角度、噪声分布跟 ImageNet 完全不一样。
所以我的建议是:
- 校准数据集最好从实际部署场景中采样
- 样本量不用大,但分布要覆盖全面
- 避免使用训练集——那会引入过拟合风险
- 如果场景数据敏感,可以用合成数据或数据增强来模拟
我的经验:校准数据集通常取 100-500 个样本就够了。我习惯先跑 200 个样本看看效果,如果精度波动大,再逐步增加到 500。再多,边际收益就很低了。
4.3 MinMax 校准方法
MinMax 是最直观的校准方法。它直接取激活值或权重的最大值和最小值,作为量化范围。
scale = (max_val - min_val) / (Q_max - Q_min)
zero_point = round(Q_min - min_val / scale)
优点很明显:实现简单,计算快,几乎不消耗额外资源。对于权重分布比较均匀的网络,效果还不错。
但缺点也很致命——对异常值极其敏感。你想想看,如果激活值里有一个离群点,比如某个神经元偶尔输出 100,而其他值都在 -5 到 5 之间。MinMax 会把量化范围拉到 -5 到 100,导致大部分有效值的量化精度被浪费。
注意:MinMax 适合权重量化,但不建议直接用于激活值量化。我在 MobileNet 上试过,用 MinMax 做激活量化,精度直接掉了 3 个点。换成 KL 散度后,只掉了 0.5 个点。
4.4 KL 散度校准方法
KL 散度方法,也叫「熵校准」。它的思路是:找一个阈值 T,把浮点值截断到 [-T, T] 范围内,然后量化。这个 T 怎么选?让量化前后的分布差异最小。
具体来说,它计算原始浮点分布 P 和量化后分布 Q 之间的 KL 散度:
D_KL(P || Q) = Σ P(x) * log(P(x) / Q(x))
然后遍历不同的 T 值,找到让 KL 散度最小的那个 T。这个 T 就是最优截断阈值。
为什么 KL 散度比 MinMax 好?因为它会主动舍弃那些「不重要」的离群点。你想想看,如果某个值出现概率极低,即使它数值很大,对整体分布的影响也微乎其微。KL 散度会自动把它截断掉,把宝贵的量化精度留给那些高频出现的值。
我举个例子。在 NLP 模型里,embedding 层的输出经常有长尾分布。用 MinMax 量化,精度掉得厉害。用 KL 散度,基本无损。我在 BERT 模型上验证过,KL 散度比 MinMax 平均高出 1.2 个点的 F1 分数。
4.5 两种方法的对比
| 对比维度 | MinMax | KL 散度 |
|---|---|---|
| 计算复杂度 | 低(O(n)) | 高(需要多次直方图统计) |
| 对离群点敏感度 | 高 | 低 |
| 适用场景 | 权重量化、分布均匀的激活值 | 激活值量化、长尾分布 |
| 精度表现 | 一般,容易受异常值影响 | 优秀,能自适应截断 |
| 校准时间 | 秒级 | 分钟级 |
我的建议:权重量化用 MinMax 就够了,因为权重分布通常比较规整。激活值量化优先用 KL 散度。如果推理速度有要求,可以先用 MinMax 快速验证,精度不行再换 KL 散度。
4.6 避坑指南
做 PTQ 时,有几个坑我踩过,分享给你:
- 校准数据量不是越多越好。 我曾经试过用 5000 张图片做校准,结果精度反而比 200 张差。后来发现是数据重复度太高,导致分布偏移。
- 不同层的分布差异很大。 有些层适合 MinMax,有些层适合 KL 散度。我习惯先跑一遍 KL 散度,然后对精度敏感层单独调优。
- BatchNorm 层要特殊处理。 量化时 BN 层的参数需要融合到卷积层里,否则会引入额外误差。这个后面章节会详细讲。
- 别忘了检查量化后的数值范围。 有时候 scale 算出来是 0 或者 NaN,通常是输入数据有问题。先跑一遍 FP32 推理,确认数据流正常。
曾经踩过的坑:有一次我量化一个检测模型,校准完精度看起来没问题。但部署到 NPU 上后,检测框全偏了。排查了两天,发现是校准数据集的标注格式跟训练时不一致,导致激活值分布偏移。从那以后,我每次做 PTQ 都会先跑一遍 FP32 推理,确认校准数据没问题。
4.7 小结
PTQ 是模型量化的入门级技术,但想用好也不简单。核心就三件事:选对校准数据、选对校准方法、验证量化效果。MinMax 简单粗暴,适合权重;KL 散度更精细,适合激活值。实际项目中,我建议两种方法都试试,哪个好用哪个。
下一章我们会讲量化感知训练(QAT),那是另一种思路——让模型在训练过程中就学会适应量化。到时候你会发现,PTQ 和 QAT 其实是互补的,不是互斥的。