4、训练后量化(PTQ):校准数据集的选择,KL散度与MSE两种校准方法

说到训练后量化,也就是 PTQ,这可能是咱们嵌入式部署中最常用的一招了。你想想看,模型训好了,直接拿来量化,不用重新训练,多省事。但这里有个关键问题——校准数据集怎么选?选不好,量化后的模型精度可能直接崩掉。

我个人习惯把 PTQ 分成两步走:第一步是选好校准数据,第二步是选好校准方法。今天咱们就重点聊聊这两件事。

校准数据集:别随便拿几张图就上

校准数据集,说白了就是用来「摸清」模型激活值分布的一组数据。量化的时候,我们需要知道每一层输出的数值范围,才能决定怎么把 float32 映射到 int8。

我在项目中遇到过这样一个坑:有次做一个人脸检测模型,随手拿了 100 张风景图做校准。结果量化后模型在测试集上直接掉了 5 个点。后来换成 500 张人脸图,精度只掉了 0.3 个点。嗯,校准数据的选择就是这么敏感。

校准数据集选择的核心原则:

  • 代表性:校准数据必须来自训练集的分布,或者至少和实际部署场景一致
  • 多样性:覆盖各种可能的输入情况,别只挑简单的
  • 数量适中:一般 200-1000 张就够了,太多反而浪费计算资源

你可能会问:「那我直接用训练集行不行?」理论上可以,但没必要。训练集太大,校准过程会变得很慢。而且,用训练集校准容易过拟合到训练数据的分布上,泛化性反而不好。

我一般会从验证集里随机抽 500 张左右。如果验证集也不大,那就用全部验证集。记住一个原则:校准数据要能代表你模型在实际场景中会遇到的数据。

KL 散度校准:让分布尽量接近

KL 散度,全称 Kullback-Leibler divergence,中文叫相对熵。它衡量的是两个概率分布之间的差异。在量化中,我们用它来找到最佳的量化阈值。

具体怎么做呢?

  1. 收集校准数据,跑一遍前向推理,记录每一层的激活值
  2. 把这些激活值统计成直方图,得到原始 float 分布的近似
  3. 尝试不同的量化阈值,把原始分布截断后量化到 int8
  4. 计算量化后的分布和原始分布的 KL 散度
  5. 选择 KL 散度最小的那个阈值

说白了,KL 散度校准就是在找一个「最优截断点」。因为 int8 只能表示 256 个值,而 float32 的范围可能很大。我们得决定哪些值可以丢掉,哪些值必须保留。

我的经验:KL 散度对激活值中的「长尾分布」特别有效。如果你的模型激活值有很多离群点,KL 散度通常比 MSE 表现好。我在做 MobileNet 量化时,KL 散度比 MSE 高了 0.8 个点。

MSE 校准:最小化量化误差

MSE,均方误差,这个大家应该很熟悉了。在量化校准中,它的思路更直接:找到一组量化参数,让量化前后的数值误差最小。

公式很简单:

MSE = (1/N) * Σ (x_float - x_quant)^2

其中 x_float 是原始 float 值,x_quant 是量化后再反量化回来的值。我们遍历所有可能的量化阈值,选 MSE 最小的那个。

MSE 校准的好处是计算简单,容易理解。但它有个问题:它对所有数值一视同仁。不管是大值还是小值,误差权重都一样。这在实际中不一定合理——有些数值范围对模型精度影响更大。

注意:MSE 校准对「均匀分布」的数据效果很好。但如果你的激活值分布严重偏斜,MSE 可能会把量化阈值选得偏大或偏小。我曾经在 ResNet-50 上对比过,当激活值分布比较集中时,MSE 和 KL 散度结果差不多;但分布很散时,KL 散度明显更优。

两种方法怎么选?

我整理了一个对比表格,方便你参考:

对比维度 KL 散度 MSE
核心思想 最小化分布差异 最小化数值误差
适用场景 长尾分布、非对称分布 均匀分布、对称分布
计算复杂度 较高(需要统计直方图) 较低(直接计算误差)
对离群点敏感度 低(会自动截断) 高(离群点会拉大误差)
实际效果 多数场景下更优 分布均匀时不错

我个人习惯的做法是:先试 KL 散度,如果精度下降在可接受范围内,就用它。如果 KL 散度效果不好,再试试 MSE。有时候两种方法结合使用效果更好——比如对某些层用 KL,对另一些层用 MSE。

避坑指南

最后分享几个我踩过的坑:

  • 校准数据太少:我曾经只用 50 张图做校准,结果量化后模型在某些类别上完全失效。后来加到 300 张,问题解决了。
  • 校准数据太「干净」:有次做工业检测模型,校准数据全是完美光照下的图片。部署到现场后,光线一变,模型精度直接掉到 60%。后来在校准数据里加了各种光照条件,才稳住。
  • 忽略 BatchNorm 层:量化前一定要把 BatchNorm 层融合到卷积层里,否则校准结果会偏差很大。这个我后面会专门讲。

嗯,关于 PTQ 的校准数据选择和两种校准方法,今天就聊这么多。记住一句话:校准数据选得好,量化成功一半。剩下的,就是选对方法,调好参数了。