模型量化实战:从FP32到INT8,精度与速度的博弈
模型量化,说白了就是把模型从“高精度慢跑”变成“低精度快跑”。FP32 是 32 位浮点数,INT8 是 8 位整数。你想想看,数据量直接缩到四分之一,推理速度自然就上去了。
但问题来了——精度会掉。掉多少?怎么控制?这就是我们今天要聊的核心。
核心观点: 量化不是简单的“砍精度”,而是用更少的比特数去逼近原始分布。关键在于找到那个“精度不掉、速度起飞”的平衡点。
2.1 量化原理:为什么能快?
FP32 的每个数占 4 字节,INT8 只占 1 字节。内存带宽省了,计算单元也能并行处理更多数据。我见过一个项目,量化后推理延迟从 120ms 降到 35ms,几乎三倍提速。
量化的数学本质很简单:
// 量化公式:将浮点数映射到整数范围
// r = S * (q - Z)
// r: 真实浮点值
// q: 量化后的整数值
// S: 缩放因子 (scale)
// Z: 零点偏移 (zero_point)
// 以对称量化为例 (Z=0)
// INT8 范围: [-128, 127]
// 假设权重范围: [-1.0, 1.0]
// S = (1.0 - (-1.0)) / (127 - (-128)) = 2.0 / 255 ≈ 0.00784
// q = round(r / S)
嗯,这里要注意。对称量化假设数据分布是对称的,但实际中很多激活值并不对称。这时候非对称量化(Z ≠ 0)会更准。
2.2 量化方式:选对路子
我个人习惯把量化方式分成三类。你在项目里选哪种,取决于你的硬件和精度要求。
| 量化方式 | 原理 | 精度损失 | 适用场景 |
|---|---|---|---|
| 权重量化 | 只量化权重,激活保持 FP32 | 低(约 0.5% 以内) | 权重占主导的模型(如全连接层多的网络) |
| 激活量化 | 权重和激活都量化 | 中(约 1-2%) | 卷积层多的模型(CNN 类) |
| 全量化 | 所有算子都走 INT8 | 高(需校准数据集) | 边缘设备、移动端推理 |
我的经验: 如果模型本身比较大(比如 ResNet-50 以上),权重量化基本不掉点。但像 MobileNet 这种轻量模型,全量化时精度可能掉 3-5%,需要做校准。
2.3 校准数据集:量化成败的关键
量化不是直接硬转的。你需要一个校准数据集,用来统计激活值的分布,从而确定 S 和 Z。
我曾经在一个项目中,直接用训练集做校准,结果推理时精度掉了 8%。后来换成验证集,只掉了 1.2%。
为什么会这样?因为训练集里有很多数据增强后的样本,分布太宽了。校准数据集应该尽量贴近真实推理时的数据分布。
# 校准数据集选择原则
# 1. 数量:500-2000 张图片足够
# 2. 分布:覆盖常见场景,不要极端
# 3. 来源:验证集或线上采样,不要用训练集
# 示例:用 PyTorch 做校准
import torch
from torch.quantization import prepare, convert
# 准备校准数据
calibration_loader = get_calibration_loader(
dataset='validation',
batch_size=32,
num_samples=1000
)
# 插入量化观察器
model.qconfig = torch.quantization.get_default_qconfig('fbgemm')
model_prepared = prepare(model)
# 校准:跑一遍前向,收集激活分布
with torch.no_grad():
for images, _ in calibration_loader:
model_prepared(images)
# 转换到 INT8
model_int8 = convert(model_prepared)
注意: 校准数据量不是越多越好。我见过有人用 10000 张图片做校准,结果分布过于平滑,反而导致精度下降。500-2000 张通常就够了。
2.4 精度与速度的博弈:我的量化避坑指南
量化不是万能的。有些坑,我踩过,希望你别再踩。
- 对称量化 vs 非对称量化:权重通常用对称量化(分布接近 0 对称),激活用非对称量化(ReLU 后全是正数)。混着用效果更好。
- 逐层量化 vs 逐通道量化:逐通道量化精度更高,但计算更复杂。我建议卷积层用逐通道,全连接层用逐层。
- 量化敏感层:有些层对量化特别敏感,比如第一层和最后一层。我习惯让它们保持 FP32。
- 混合精度量化:不是所有层都需要 INT8。敏感层用 FP16,其他层用 INT8,效果往往比全量化好。
避坑指南: 我曾经在一个语音识别模型上做全量化,结果 WER(词错误率)从 8% 飙升到 15%。后来发现是 BatchNorm 层在量化后统计量偏移了。解决方案:把 BN 层融合到卷积层里再量化。
2.5 量化后的验证流程
量化完别急着上线。先跑一遍验证流程,确保精度在可接受范围内。
| 步骤 | 操作 | 检查项 |
|---|---|---|
| 1 | 跑 FP32 基线 | 记录原始精度(如 Top-1 准确率) |
| 2 | 跑 INT8 量化模型 | 对比精度差异,控制在 1% 以内 |
| 3 | 逐层对比输出 | 检查每层的输出差异(余弦相似度 > 0.99) |
| 4 | 端到端测试 | 用真实数据跑一遍,看业务指标 |
小技巧: 如果精度掉得厉害,先检查第一层和最后一层的量化参数。这两个地方最容易出问题。
2.6 量化知识体系总览
下面这张图,是我自己整理的量化知识体系。你可以把它当成一张地图,遇到问题就知道该往哪查。
这张图把量化分成三个核心分支:量化方式、校准数据集、避坑指南。你在实际项目中,可以按这个结构去排查问题。
最后提醒: 量化不是银弹。如果你的模型本身精度就不高(比如 Top-1 只有 60%),量化后可能直接崩到 50% 以下。先确保 FP32 基线足够好,再考虑量化。