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 散度,也叫相对熵。它衡量的是两个概率分布之间的差异。
在量化里,我们比较的是:原始浮点值的分布和量化后反量化回来的值的分布。
流程是这样的:
- 统计原始数据的直方图(比如 2048 个 bin)。
- 尝试不同的截断阈值(比如从 128 开始,逐渐缩小)。
- 对每个阈值,把直方图量化到 256 个 bin,再反量化回来。
- 计算原始直方图和反量化直方图的 KL 散度。
- 选择 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 的三种方法串起来了:
4.7 实际项目中的选择策略
说了这么多理论,到底怎么选?
我总结了一个简单的决策流程:
- 先跑 MinMax。如果精度损失 < 1%,直接用。省时间。
- 精度损失在 1%~3%,换成 KL 散度。大部分模型都能救回来。
- 精度损失 > 3%,试试 MSE。特别是模型的最后几层,MSE 往往有奇效。
- 还不行?那就得考虑混合精度了——敏感层保留 FP16,其他层用 INT8。
一个小技巧:校准数据集的大小,我一般取 500~2000 张。太少,统计不准;太多,浪费时间。另外,校准数据最好来自训练集,分布和训练数据一致。
4.8 避坑指南
最后,分享几个我踩过的坑:
- 校准数据不能太单一。有一次我只用了猫的图片做校准,结果模型对狗的分类精度掉了 4%。后来换成混合数据集,问题解决。
- 注意 BN 层的融合。PTQ 之前,一定要先把 BN 层融合到卷积层里。否则量化误差会放大。
- 逐层检查量化误差。不要只看最终精度。我会把每一层的输出都 dump 出来,对比浮点和量化版本的 MSE。哪层误差大,就针对哪层调量化参数。
嗯,PTQ 的内容就这些。三种方法,各有优劣。关键是根据你的模型和数据特点,选对方法。