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 其实是互补的,不是互斥的。

专注资料整理