修复策略总览:量化感知训练、部分量化、混合精度与校准优化
模型量化后精度掉了,怎么办?
别慌。这几乎是每个做量化的工程师都会遇到的坎。我刚开始接触量化时,也天真地以为跑完校准就万事大吉,结果模型精度直接掉了 5 个点,被业务方追着问了一周。
后来我总结出一套修复策略。说白了,就是四个方向:量化感知训练(QAT)、部分量化、混合精度量化、校准数据集优化。今天我把它们掰开揉碎讲清楚。
1. 量化感知训练(QAT)
QAT 是目前修复精度最有效的手段之一。它的思路很简单:在训练过程中模拟量化误差,让模型自己学会适应。
具体做法是在计算图中插入伪量化节点(Fake Quantize Node)。前向传播时,这些节点模拟 INT8 的舍入和截断行为;反向传播时,梯度仍然用浮点精度更新。这样模型在训练中就「见过」量化噪声了,部署时切换到真实量化,精度损失会小很多。
我曾经在一个语义分割模型上试过,直接 PTQ 后 mIoU 掉了 4.2%。用 QAT 微调了 3 个 epoch,精度只掉了 0.3%。效果很明显,但代价是训练时间增加了。
# PyTorch 中启用 QAT 的典型流程
import torch.quantization as quant
# 准备模型
model = MyModel()
model.load_state_dict(torch.load('float_model.pth'))
model.train()
# 插入伪量化节点
model.qconfig = quant.get_default_qat_qconfig('fbgemm')
quant.prepare_qat(model, inplace=True)
# 微调
for epoch in range(3):
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
# 转换为量化模型
model.eval()
quant.convert(model, inplace=True)
2. 部分量化(Partial Quantization)
不是所有层都对量化敏感。有些层量化后精度几乎不变,有些层一量化就崩。部分量化的思路就是:只量化那些「皮实」的层,敏感层保留浮点。
怎么找敏感层?我一般用两种方法:
- 逐层精度分析:每次只量化一个层,观察精度变化。变化大的就是敏感层。
- 激活值分布检查:如果某层的激活值分布特别宽(比如范围超过 [-10, 10]),量化后信息损失会很大。
我记得有一次做 NLP 模型量化,Embedding 层量化后精度直接崩了。后来我把 Embedding 层单独保留 FP32,其他层全部 INT8,精度几乎无损。
| 层类型 | 量化敏感度 | 建议策略 |
|---|---|---|
| Conv2d(深度可分离) | 低 | 可量化 |
| Linear(全连接) | 中 | 视情况量化 |
| Embedding | 高 | 建议保留 FP32 |
| BatchNorm | 低 | 可量化 |
| LayerNorm | 高 | 建议保留 FP32 |
| Attention(Softmax 附近) | 高 | 建议保留 FP32 |
3. 混合精度量化(Mixed Precision)
混合精度和部分量化有点像,但更细粒度。部分量化是「层级别」的,混合精度可以做到算子级别甚至通道级别。
举个例子:一个 Conv2d 层,权重用 INT8,激活用 INT16,或者权重用 FP16,激活用 INT8。不同硬件支持的混合精度组合不一样。
我建议你优先关注权重和激活的位宽组合:
- W8A8:标准 INT8 量化,大部分硬件支持。
- W4A8:权重用 INT4,激活用 INT8。适合存储受限的场景。
- W8A16:权重 INT8,激活 INT16。适合激活值分布宽的模型。
- FP16 + INT8:权重 FP16,激活 INT8。某些 GPU 上效率很高。
4. 校准数据集优化
这个策略最容易被忽略,但往往成本最低、效果最明显。
校准数据集是用来确定量化参数(scale 和 zero_point)的。如果校准数据分布和真实数据分布不一致,量化参数就会偏,精度自然掉。
我踩过这个坑。有一次做图像分类量化,用了 500 张 ImageNet 验证集做校准,精度掉了 2%。后来换成 2000 张训练集,精度只掉了 0.5%。
优化校准数据集,我总结了三条原则:
- 样本量要够:一般建议 500-2000 张,太少统计不稳定。
- 覆盖所有类别:每个类别至少 10-20 张,避免分布偏移。
- 包含边界样本:比如低光照、高噪声、极端角度。这些样本能拉大量化范围,减少截断误差。
策略对比与选择
四种策略各有适用场景。我整理了一张对比表,方便你快速决策:
| 策略 | 精度修复效果 | 实施成本 | 适用场景 |
|---|---|---|---|
| 量化感知训练(QAT) | ★★★★★ | 高(需要训练) | 有训练环境,精度要求极高 |
| 部分量化 | ★★★★ | 中(需要逐层分析) | 模型结构复杂,部分层敏感 |
| 混合精度量化 | ★★★★ | 中高(依赖硬件) | 硬件支持混合精度指令 |
| 校准数据集优化 | ★★★ | 低(只需换数据) | 校准集分布偏差大 |
实际项目中,我通常的流程是:先优化校准数据集(成本最低),如果精度还不够,再做逐层分析找敏感层(部分量化),最后才考虑 QAT。混合精度量化一般放在硬件适配阶段做。
好了,这四种策略的框架就讲到这里。后面几章我会逐一深入,带你看代码实现和实际案例。记住,修复精度损失不是一锤子买卖,而是一个迭代过程。多试、多对比、多记录,慢慢你就有感觉了。