3. 训练后量化(PTQ):PTQ原理、校准数据集、KL散度与熵校准、PTQ vs QAT对比

好,咱们进入第三个章节。训练后量化,英文叫 Post-Training Quantization,简称 PTQ。这名字起得很直白——训练完了,再来量化。说白了,就是模型已经训好了,我们拿着这个“成品”去做压缩。

我个人习惯把 PTQ 看作是“性价比之王”。为什么这么说?你想想看,不需要重新训练,不需要动你的训练代码,只需要跑几遍推理,就能把模型从 FP32 压到 INT8,推理速度翻倍甚至翻三倍。我在项目中遇到过不少团队,模型训了半个月,一听说要 QAT(量化感知训练)还得再训几天,直接摇头。这时候 PTQ 就是他们的救星。

3.1 PTQ 的核心原理

PTQ 的原理其实不复杂。我们有一组训练好的浮点权重,现在要把它映射到 INT8 的整数空间。这个映射过程,核心就是找两个东西:缩放因子(scale)零点(zero point)

公式很简单:

q = round(r / scale) + zero_point

其中 r 是浮点数,q 是量化后的整数。反过来,反量化就是:

r = (q - zero_point) * scale

嗯,这里要注意:scale 怎么选?选大了,精度损失大;选小了,容易溢出。所以 PTQ 的核心工作,就是找到最合适的 scale 和 zero_point。

那怎么找呢?这就需要用到校准数据集了。

3.2 校准数据集:PTQ 的“试金石”

校准数据集,英文叫 Calibration Dataset。它不是用来训练的,而是用来“试探”模型在真实数据上的激活值分布。

我刚开始做 PTQ 时犯过一个错误:随便拿了几张图就跑校准。结果量化后的模型在测试集上直接崩了。后来才明白,校准数据集必须满足两个条件:

  • 代表性:数据分布要和真实部署场景一致。比如你做自动驾驶,校准集里全是晴天白天的图,那模型到了雨天晚上肯定拉胯。
  • 多样性:覆盖尽可能多的输入模式。不要只用一类样本。

一般建议校准集的大小在 100~500 张左右。太少,统计不准;太多,校准时间太长,收益也不大。

我的小技巧:如果训练集很大,我会从训练集中随机抽取 200 张作为校准集。注意要打乱顺序,确保类别均衡。我曾经遇到过校准集里全是背景图的情况,结果量化后模型对前景物体完全失效——嗯,血的教训。

3.3 KL 散度与熵校准

好,校准集有了,接下来怎么选 scale?最常用的方法之一就是KL 散度校准,也叫熵校准

为什么用 KL 散度?说白了,就是衡量两个分布之间的“距离”。我们希望量化后的 INT8 分布,尽可能接近原始的 FP32 分布。KL 散度越小,说明量化损失越小。

具体做法是这样的:

  1. 在校准集上跑一遍推理,收集每一层的激活值分布。
  2. 把这个分布做成直方图,比如 2048 个 bin。
  3. 尝试不同的阈值 T,把直方图截断到 [-T, T] 范围内。
  4. 将截断后的分布量化到 256 个 bin(对应 INT8)。
  5. 计算量化前后的 KL 散度。
  6. 选择 KL 散度最小的那个 T,作为 scale 的依据。

你可能会问:为什么要截断?因为 FP32 的分布往往有长尾,那些极少出现的极端值如果保留,会浪费 INT8 的表示范围。截断掉尾部,反而能提高中间区域的精度。

核心思想:KL 散度校准的本质,是在“精度损失”和“表示范围”之间找一个平衡点。截断越多,表示范围越集中,但丢失的信息也越多。KL 散度帮我们自动找到这个最优截断点。

TensorRT 默认使用的就是 KL 散度校准。我记得第一次用 TensorRT 做 PTQ 时,看到它自动选出来的阈值,跟我手动调了好几天才找到的几乎一样——那一刻,我承认我服了。

3.4 PTQ vs QAT 对比

讲完了 PTQ,咱们来聊聊它和 QAT(量化感知训练)的区别。很多同学问我:到底该用 PTQ 还是 QAT?

我的回答是:先试 PTQ,不行再上 QAT

为什么?看这张对比表你就明白了:

对比维度 PTQ(训练后量化) QAT(量化感知训练)
是否需要训练 不需要 需要,在量化模拟下微调
所需数据 少量校准集(100~500张) 需要训练集或大量数据
实现复杂度 低,几行代码搞定 高,需要修改训练代码
精度损失 通常较小,大模型损失更小 更小,接近 FP32 精度
适用场景 快速部署、大模型、资源紧张 精度敏感、小模型、有训练资源
推理速度 快(INT8 加速) 快(INT8 加速)

你看,PTQ 最大的优势就是“快”和“省”。不需要动训练流程,不需要 GPU 跑几天微调。对于大模型(比如 ResNet-50 以上),PTQ 的精度损失往往在 1% 以内,完全可接受。

但 QAT 也有它的用武之地。我曾经在一个轻量级模型(MobileNetV2)上试过 PTQ,精度直接掉了 5 个点。为什么?小模型的表示能力弱,量化带来的噪声影响更大。这时候 QAT 就派上用场了——通过在训练中模拟量化误差,让模型学会“适应”量化。

避坑指南:我曾经在一个项目中,PTQ 后模型精度掉了 3%,团队觉得还能接受就直接上线了。结果线上数据分布和校准集有偏差,实际精度掉了 8%。所以我的建议是:PTQ 后一定要在真实场景数据上做验证,不要只看测试集指标。

最后总结一下我的经验:

  • 模型大于 50MB:优先 PTQ,大概率够用。
  • 模型小于 10MB:直接上 QAT,别犹豫。
  • 中间地带:先 PTQ 试水,精度损失超过 2% 再切 QAT。

好了,PTQ 的原理、校准集、KL 散度、以及和 QAT 的对比,咱们都聊透了。下一章我会带你手把手跑一遍 PTQ 的代码,看看实际效果如何。