训练后量化(PTQ)原理:校准数据集、动态量化、静态量化、量化粒度
训练后量化,英文叫 Post-Training Quantization,简称 PTQ。说白了,就是模型训练完了,我们直接拿它做手脚,把权重和激活值从 FP32 砍成 INT8 甚至更低精度。这招在工业界用得最多,因为它快,不需要重新训练。
我个人习惯把 PTQ 比作「给模型减肥」。模型训练好比练出了一身肌肉,PTQ 就是把这身肌肉里的水分挤掉,留下干货。挤得好,模型跑得快还省内存;挤不好,精度掉得你怀疑人生。
校准数据集:量化的「标尺」
做静态量化时,我们需要知道激活值的分布范围——最小值是多少,最大值是多少。这个信息从哪来?从一小部分真实数据里统计出来。这一小部分数据,就叫校准数据集。
校准数据集的选择很有讲究。我在项目中遇到过有人随便拿几百张训练集图片去校准,结果量化后的模型在测试集上直接崩了。为什么?因为训练集和真实场景的数据分布不一样。
校准的过程是这样的:我们把校准数据喂给模型跑一遍前向推理,同时记录每一层激活值的统计信息——比如 min、max、直方图。然后根据这些统计信息,算出每个 Tensor 的量化参数(scale 和 zero_point)。
嗯,这里要注意:校准数据集不能参与训练,它只用来收集统计量。我见过有人不小心把校准数据混进训练集,结果量化后的模型过拟合了,跑新数据效果很差。
动态量化 vs 静态量化
这两个概念经常被搞混。我简单解释一下。
动态量化:权重提前量化好,但激活值在推理时动态计算量化参数。每次推理都要算一遍 scale 和 zero_point,所以速度提升有限,但精度损失小。
静态量化:权重和激活值的量化参数都提前算好,推理时直接用量化后的整数计算。速度快,但需要校准数据集来提前统计激活值分布。
| 对比项 | 动态量化 | 静态量化 |
|---|---|---|
| 权重 | 提前量化 | 提前量化 |
| 激活值 | 推理时动态计算 | 提前校准,固定参数 |
| 是否需要校准集 | 不需要 | 需要 |
| 推理速度提升 | 中等(1.5-2x) | 高(2-4x) |
| 精度损失 | 较小 | 稍大,但可控 |
| 适用场景 | CPU 推理、LSTM/Transformer | GPU/NPU 推理、CNN |
我个人的经验是:如果你的模型跑在 CPU 上,尤其是 NLP 模型(比如 BERT),动态量化是首选。精度几乎不掉,速度还能快一倍。但如果是 CNN 模型跑在 GPU 或 NPU 上,静态量化才是王道。
量化粒度:per-tensor vs per-channel
量化粒度,说白了就是「一个量化参数管多大范围」。这个选择直接影响精度和计算效率的平衡。
Per-tensor 量化:整个 Tensor(比如一个卷积层的输出)共享同一个 scale 和 zero_point。简单粗暴,计算快,但精度损失大。
Per-channel 量化:每个输出通道有自己的量化参数。精度高,但计算稍微复杂一点。
为什么会这样?你想想看,一个卷积层有 64 个输出通道,每个通道的数值分布可能差别很大。如果所有通道共用一套量化参数,那些数值范围小的通道就会被「压缩」得很厉害,信息丢失严重。
我曾经在一个目标检测模型上踩过这个坑。用 per-tensor 量化后,mAP 掉了 3 个点。换成 per-channel 量化,只掉了 0.5 个点。差别就这么大。
- 权重量化:强烈建议用 per-channel。精度提升明显,计算开销增加不大。
- 激活值量化:一般用 per-tensor 就够了。因为激活值的分布通常比较均匀,per-channel 带来的收益有限。
- 如果你用的是小模型(比如 MobileNet),per-channel 几乎是必须的。大模型(比如 ResNet-50)对量化更鲁棒,per-tensor 也能接受。
PTQ 的核心流程
下面这张图展示了 PTQ 的完整流程。我建议你仔细看看,尤其是校准和量化参数计算那两步,最容易出错。
实战中的避坑指南
讲完了原理,我分享几个实战中容易踩的坑。
第一个坑:校准集和测试集分布不一致。 我曾经在一个工业检测项目上,用实验室采集的数据做校准,结果模型部署到产线上,精度直接掉了 5 个点。后来发现产线上的光照条件和实验室完全不同。解决办法很简单:从产线上实时采集几百张图片做校准。
第二个坑:忽略激活值中的异常值。 有些层的激活值会出现个别特别大的值(outlier),如果直接用 min/max 做量化,整个量化参数都会被带偏。我建议用百分位法,比如取 99.9% 的分位数作为 max,而不是最大值。
第三个坑:per-channel 量化在硬件上不支持。 有些 NPU 只支持 per-tensor 量化。做之前一定要查清楚目标硬件的文档。我吃过这个亏,模型量化好了,部署时发现硬件不支持 per-channel,只能重新来。
好了,PTQ 的核心内容就这些。记住一句话:量化不是玄学,是统计学。只要数据选对了,参数调好了,精度损失完全可以控制在 1% 以内。