量化类型:PTQ与QAT的区别、动态量化与静态量化、权重量化与激活量化
聊到量化,大家最常听到的两个词就是PTQ和QAT。说实话,我刚入行那会儿也觉得这俩东西差不多,反正都是把模型变小嘛。后来踩了坑才明白——它们俩的思路完全不同,适用场景也天差地别。
PTQ:事后诸葛亮式的量化
Post-Training Quantization,直译就是“训练后量化”。说白了,模型已经训练好了,我们拿过来直接做量化。不需要重新训练,也不需要动你的训练代码。
PTQ又分两种:
- 权重量化:只把权重转成int8,激活值不动。这个最简单,基本无感。
- 全量化:权重和激活值都量化。这个就需要一点点校准数据来统计激活值的范围。
我个人的习惯是,如果模型比较大(比如ResNet50以上),先试试PTQ。因为大模型本身冗余多,量化掉一点精度损失往往可以接受。我在一个OCR项目里试过,PTQ后精度只掉了0.3%,但推理速度翻了将近两倍。
QAT:让模型学会“忍受”量化
Quantization-Aware Training,量化感知训练。这个名字起得好——让模型在训练阶段就“感知”到量化操作的存在。
QAT的核心思路是:在训练过程中插入伪量化节点(Fake Quantize),模拟量化带来的误差。这样模型在反向传播时,会主动调整参数来适应量化后的精度损失。
嗯,这里要注意:QAT并不是从头开始训练。通常的做法是:
- 先正常训练一个浮点模型(或者加载预训练权重)
- 在模型里插入伪量化节点
- 用很小的学习率(比如1e-5)再微调几个epoch
我曾经在一个语义分割项目里吃过亏。模型用PTQ后,mIoU直接从78%掉到了62%,完全没法用。后来换成QAT微调了3个epoch,精度回到了76%。说白了,如果你的模型对精度特别敏感,QAT几乎是必选项。
动态量化 vs 静态量化
这两个概念经常和PTQ/QAT混在一起说。我帮你理一下:
| 对比项 | 动态量化 | 静态量化 |
|---|---|---|
| 权重 | 量化成int8 | 量化成int8 |
| 激活值 | 推理时动态计算范围 | 预先统计好范围(校准) |
| 速度提升 | 中等(约1.5-2倍) | 较大(约2-4倍) |
| 适用场景 | NLP模型(如BERT) | CV模型(如CNN) |
为什么NLP模型更适合动态量化?因为NLP模型的激活值分布变化很大,不同句子输入后,中间层的数值范围可能差好几个数量级。你想想看,如果硬要静态量化,那校准集选不好就容易翻车。
我做过一个BERT的部署,用动态量化效果就很好。精度几乎无损,推理速度提升了1.8倍。但换成静态量化,精度直接掉了2个点,而且不同batch size下表现还不稳定。
权重量化 vs 激活量化
这两个其实很好理解:
- 权重量化:把模型的权重参数从FP32转成INT8。权重是固定的,量化起来最安全。
- 激活量化:把每一层的输出(激活值)也量化。激活值是动态的,量化难度大一些。
为什么权重好量化?因为权重在推理时是不变的。你可以在部署前就统计好每个权重的最大值、最小值,然后算出缩放因子。但激活值不一样——输入图片不同,激活值就不同。
我刚开始做量化时犯过一个错误:只量化权重,不量化激活。结果发现推理速度提升有限。后来才明白,真正吃计算资源的是激活值之间的矩阵乘法。只量化权重,计算时还得把激活值转成FP32,等于白干。
知识体系总览
下面这张图帮你理清本章的核心逻辑:
实际项目中的选择策略
说了这么多理论,到底怎么选?我一般按这个流程来:
- 先试PTQ:如果精度损失在1%以内,直接上PTQ,省时省力
- 精度损失大?:试试动态量化(尤其是NLP模型)
- 还不行?:上QAT,微调3-5个epoch
- 终极方案:QAT + 知识蒸馏,把大模型的知识教给小模型
我记得有一次做车载摄像头模型,精度要求特别高(mAP不能掉超过0.5%)。PTQ直接掉了1.2%,动态量化也不行。最后用QAT微调了5个epoch,精度只掉了0.3%,完美达标。
所以你看,没有最好的量化方法,只有最合适的。关键是要理解每种方法的原理和适用场景,然后根据你的模型、数据和部署平台来灵活选择。