4、后训练量化:快速部署的捷径—— 校准数据集、KL散度与对称/非对称量化

说到模型部署,我最常被问到的一个问题是:“模型太大,跑不动,怎么办?”

嗯,答案其实不复杂。除了剪枝和蒸馏,还有一个更直接、更暴力的方法——后训练量化(Post-Training Quantization, PTQ)。说白了,就是把模型里的浮点数(FP32)换成整数(INT8)。

你想想看,一个模型从 32 位变成 8 位,体积直接缩到四分之一。推理速度呢?在支持 INT8 的硬件上,能快 2 到 4 倍。我在项目中遇到过好几次,模型精度掉得不多,但速度翻倍,那种感觉真的很爽。

4.1 什么是后训练量化?

后训练量化,就是模型训练完之后,我们直接对权重和激活值做“压缩”。不需要重新训练,也不需要改网络结构。

它的核心思路很简单:找到浮点数的分布范围,然后映射到整数的范围里。

举个例子:

  • 原始权重范围:[-1.0, 1.0]
  • INT8 范围:[-128, 127]
  • 映射公式:q = round(r / scale) + zero_point

这里的 scalezero_point 就是我们要算的关键参数。

核心要点:后训练量化不需要反向传播,只需要前向推理一次或几次,就能完成量化。所以它特别适合快速部署的场景。

4.2 校准数据集:量化前的“摸底考试”

量化不是随便找个范围就行的。你得知道模型在实际数据上的激活值分布是什么样的。

这就是校准数据集(Calibration Dataset)的作用。

我个人习惯从训练集中抽一小部分数据,大概几百到几千张图片,作为校准集。然后让模型跑一遍前向推理,记录每一层的激活值分布。

为什么要这么做?

  • 权重是固定的,可以直接统计范围。
  • 激活值是动态的,不同输入会产生不同分布。
  • 校准集要尽量覆盖真实场景,否则量化后精度会崩。

小技巧:校准集的数量不用太多。我一般用 500 张图片就够了。太多反而浪费时间,太少又不够稳定。你可以试试 200 到 1000 张之间,效果差别不大。

4.3 KL散度:找到最优的量化范围

校准完数据,我们拿到了激活值的分布。接下来要解决的问题是:怎么选量化范围,才能让精度损失最小?

这里就要请出 KL 散度(Kullback-Leibler Divergence)了。

KL 散度衡量的是两个分布之间的差异。在量化里,我们比较的是:

  • 原始浮点数的分布(P)
  • 量化后再反量化回来的分布(Q)

我们希望这两个分布越接近越好。KL 散度越小,说明量化损失越小。

具体做法是这样的:

  1. 统计原始激活值的直方图。
  2. 尝试不同的截断阈值(比如从最大值往下砍一点)。
  3. 对每个阈值,计算量化后的分布,再反量化回来。
  4. 计算 KL 散度,选最小的那个阈值。

为什么不用最大值? 因为激活值里可能有极少数异常大的值。如果直接用最大值做范围,会导致大部分值被压缩到很小的区间里,精度损失反而更大。KL 散度能帮我们“砍掉”这些异常值,找到更合理的范围。

我曾经在一个目标检测模型上试过,直接用最大值量化,mAP 掉了 3 个点。换成 KL 散度校准后,只掉了 0.5 个点。差距还是很明显的。

4.4 对称量化 vs 非对称量化

聊完校准,我们来说说量化的两种基本形式。

4.4.1 对称量化

对称量化,就是量化范围关于 0 对称。公式很简单:

scale = max(|r_max|, |r_min|) / 127
zero_point = 0
q = round(r / scale)

优点:

  • 计算简单,不需要 zero_point。
  • 硬件实现方便,很多 NPU 只支持对称量化。

缺点:

  • 如果数据分布不对称(比如全是正数),会浪费一半的量化范围。

4.4.2 非对称量化

非对称量化允许范围不对称,用 zero_point 来偏移:

scale = (r_max - r_min) / 255
zero_point = round(-r_min / scale)
q = round(r / scale) + zero_point

优点:

  • 能充分利用 INT8 的 256 个级别,精度更高。

缺点:

  • 多了一个 zero_point,计算稍微复杂一点。
  • 某些硬件不支持。
对比项 对称量化 非对称量化
zero_point 固定为 0 需要计算
范围利用率 低(数据不对称时)
硬件支持 广泛 部分支持
精度 一般 更好

注意:我在项目中踩过一个坑。当时用非对称量化,精度表现很好。但部署到某款边缘芯片上时,发现它不支持非对称量化,只能重新校准。所以,选哪种方式,一定要先看目标硬件的文档。

4.5 实战建议:如何选择量化策略?

说了这么多,到底该怎么选?我总结了几条经验:

  • 权重用对称量化:权重的分布通常比较对称,用对称量化就够了。
  • 激活值用非对称量化:激活值经常是 ReLU 后的正数,非对称量化更合适。
  • 校准方法优先选 KL 散度:它比 min-max 和 percentile 更稳定。
  • 校准集要贴近真实数据:别拿训练集里的纯背景图去校准,模型会“学歪”。

我的习惯:先用默认的对称量化跑一遍,看看精度。如果掉点超过 1%,再换成非对称量化 + KL 散度校准。大部分情况下,这样就能把精度拉回来。

后训练量化,说白了就是一条快速部署的捷径。它不需要你动模型结构,也不需要重新训练。只要校准集选得好,量化策略选得对,精度损失完全可以控制在可接受范围内。

嗯,下一章我们会聊量化感知训练(QAT),那是另一种更精细的玩法。但如果你赶时间,PTQ 绝对是你的首选。