4. 训练后量化(PTQ):MinMax量化、KL散度量化、MSE量化

训练后量化,简称 PTQ。说白了,就是模型训练完了,我们直接拿它做量化。

不需要重新训练,也不需要反向传播。你只需要准备一小部分校准数据,跑一遍前向推理,统计出激活值和权重的分布,然后算出量化参数。

我个人习惯把 PTQ 叫做“懒人量化法”。为什么?因为它快,成本低,效果还往往不错。我在好几个边缘端芯片项目里,都是靠 PTQ 把模型压到 8-bit,精度损失控制在 1% 以内。

4.1 量化参数怎么来的?

不管用哪种方法,核心都是找两个数:缩放因子(scale)和零点(zero-point)。

公式很简单:

q = round( r / scale ) + zero_point

反过来,反量化就是:

r = (q - zero_point) × scale

所以,PTQ 的本质就是:用统计方法,找到最合适的 scale 和 zero-point。

核心观点:不同的量化方法,区别就在于“如何定义最合适”。MinMax 看极值,KL 看分布相似度,MSE 看误差平方和。

4.2 MinMax 量化:最直接的方法

MinMax 的思路很简单:找到张量的最大值和最小值,然后映射到量化范围。

公式:

scale = (max - min) / (Qmax - Qmin)
zero_point = round(Qmin - min / scale)

举个例子。假设激活值范围是 [-1.0, 3.0],量化到 8-bit(0~255):

scale = (3.0 - (-1.0)) / (255 - 0) = 4.0 / 255 ≈ 0.0157
zero_point = round(0 - (-1.0) / 0.0157) = round(63.7) = 64

优点:实现简单,计算量小。硬件实现起来也容易。

缺点:对离群点非常敏感。如果数据里有一个很大的异常值,整个量化范围就被拉宽了,精度会严重下降。

我曾经踩过的坑:有一次做图像分类模型量化,MinMax 之后精度掉了 5%。查了半天,发现是某张校准图里有一个像素值异常高。去掉那张图,精度就回来了。所以,用 MinMax 之前,一定要做数据清洗。

4.3 KL 散度量化:保分布

KL 散度,也叫相对熵。它衡量的是两个概率分布之间的差异。

在量化里,我们比较的是:原始浮点值的分布和量化后反量化回来的值的分布。

流程是这样的:

  1. 统计原始数据的直方图(比如 2048 个 bin)。
  2. 尝试不同的截断阈值(比如从 128 开始,逐渐缩小)。
  3. 对每个阈值,把直方图量化到 256 个 bin,再反量化回来。
  4. 计算原始直方图和反量化直方图的 KL 散度。
  5. 选择 KL 散度最小的那个阈值。

你想想看,为什么 KL 散度比 MinMax 好?

因为它会主动舍弃一些离群点。只要这些离群点占比不大,丢掉它们反而能让大部分数据的量化精度更高。

个人经验:KL 散度量化在 NLP 模型上效果特别好。Transformer 的激活值分布往往有长尾,MinMax 会被尾巴拉宽,KL 散度能自动把尾巴截掉。我在 BERT 模型上试过,KL 散度比 MinMax 精度高 2~3%。

4.4 MSE 量化:最小化误差

MSE,均方误差。目标就是让量化误差的平方和最小。

公式:

MSE = mean( (r - r_quant)² )

其中 r 是原始浮点值,r_quant 是量化再反量化回来的值。

做法和 KL 散度类似,也是遍历不同的截断阈值,找到 MSE 最小的那个。

区别在哪?

方法 优化目标 适用场景
MinMax 不丢失任何极值 数据分布均匀,无离群点
KL 散度 保持分布形状相似 长尾分布,NLP 模型
MSE 最小化数值误差 对数值精度敏感的层(如回归头)

我个人习惯:卷积层用 KL 散度,全连接层用 MSE。为什么?卷积层的激活值分布往往比较集中,KL 散度能保分布;全连接层的输出对数值精度更敏感,MSE 直接优化误差更靠谱。

4.5 三种方法对比

嗯,这里我把它们放在一起对比一下:

维度 MinMax KL 散度 MSE
计算复杂度 低 中 高
离群点敏感度 高 低 中
精度(一般情况) 中 高 高
硬件友好度 高 中 低
校准数据需求 少(几百张) 中(几千张) 中(几千张)

我的建议:项目初期先用 MinMax 快速验证可行性。如果精度不够,再换成 KL 散度或 MSE。不要一上来就上最复杂的方法,浪费时间。

4.6 知识体系总览

下面这张图,把 PTQ 的三种方法串起来了:

训练后量化(PTQ)三种方法对比 训练后量化(PTQ)核心方法 PTQ 量化参数计算 MinMax 量化 基于极值映射 KL 散度量化 基于分布相似度 MSE 量化 基于误差最小化 特性 简单快速 对离群点敏感 特性 保分布形状 适合长尾分布 特性 数值精度高 计算量大 推荐场景 快速验证、均匀分布 推荐场景 NLP、Transformer 推荐场景 回归头、敏感层

4.7 实际项目中的选择策略

说了这么多理论,到底怎么选?

我总结了一个简单的决策流程:

  1. 先跑 MinMax。如果精度损失 < 1%,直接用。省时间。
  2. 精度损失在 1%~3%,换成 KL 散度。大部分模型都能救回来。
  3. 精度损失 > 3%,试试 MSE。特别是模型的最后几层,MSE 往往有奇效。
  4. 还不行?那就得考虑混合精度了——敏感层保留 FP16,其他层用 INT8。

一个小技巧:校准数据集的大小,我一般取 500~2000 张。太少,统计不准;太多,浪费时间。另外,校准数据最好来自训练集,分布和训练数据一致。

4.8 避坑指南

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

  • 校准数据不能太单一。有一次我只用了猫的图片做校准,结果模型对狗的分类精度掉了 4%。后来换成混合数据集,问题解决。
  • 注意 BN 层的融合。PTQ 之前,一定要先把 BN 层融合到卷积层里。否则量化误差会放大。
  • 逐层检查量化误差。不要只看最终精度。我会把每一层的输出都 dump 出来,对比浮点和量化版本的 MSE。哪层误差大,就针对哪层调量化参数。

嗯,PTQ 的内容就这些。三种方法,各有优劣。关键是根据你的模型和数据特点,选对方法。