模型量化实战:从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 精度与速度的博弈:我的量化避坑指南

量化不是万能的。有些坑,我踩过,希望你别再踩。

  1. 对称量化 vs 非对称量化:权重通常用对称量化(分布接近 0 对称),激活用非对称量化(ReLU 后全是正数)。混着用效果更好。
  2. 逐层量化 vs 逐通道量化:逐通道量化精度更高,但计算更复杂。我建议卷积层用逐通道,全连接层用逐层。
  3. 量化敏感层:有些层对量化特别敏感,比如第一层和最后一层。我习惯让它们保持 FP32。
  4. 混合精度量化:不是所有层都需要 INT8。敏感层用 FP16,其他层用 INT8,效果往往比全量化好。
避坑指南: 我曾经在一个语音识别模型上做全量化,结果 WER(词错误率)从 8% 飙升到 15%。后来发现是 BatchNorm 层在量化后统计量偏移了。解决方案:把 BN 层融合到卷积层里再量化。

2.5 量化后的验证流程

量化完别急着上线。先跑一遍验证流程,确保精度在可接受范围内。

步骤 操作 检查项
1 跑 FP32 基线 记录原始精度(如 Top-1 准确率)
2 跑 INT8 量化模型 对比精度差异,控制在 1% 以内
3 逐层对比输出 检查每层的输出差异(余弦相似度 > 0.99)
4 端到端测试 用真实数据跑一遍,看业务指标
小技巧: 如果精度掉得厉害,先检查第一层和最后一层的量化参数。这两个地方最容易出问题。

2.6 量化知识体系总览

下面这张图,是我自己整理的量化知识体系。你可以把它当成一张地图,遇到问题就知道该往哪查。

模型量化知识体系 量化原理 量化方式 权重量化 激活量化 全量化 校准数据集 500-2000 样本 验证集/线上采样 避坑指南 敏感层保留 FP32 BN 融合 混合精度 核心原则 1. 量化不是简单的精度砍半,而是用更少的比特数逼近原始分布 2. 校准数据集的选择直接影响量化效果,500-2000 样本足够 3. 敏感层(第一层、最后一层、BN 层)建议保留 FP32 或做混合精度

这张图把量化分成三个核心分支:量化方式、校准数据集、避坑指南。你在实际项目中,可以按这个结构去排查问题。

最后提醒: 量化不是银弹。如果你的模型本身精度就不高(比如 Top-1 只有 60%),量化后可能直接崩到 50% 以下。先确保 FP32 基线足够好,再考虑量化。