模型量化基础:从浮点到整数的思维转变

模型量化,说白了就是把模型里那些高精度的浮点数(FP32),用低精度的整数(INT8)甚至更低比特来表示。你想想看,一个模型动辄几百兆,塞进边缘设备里根本跑不动。量化就是帮模型「减肥」——减掉那些不必要的精度,换来更快的速度和更小的体积。

我在项目中遇到过不少同学,一听到量化就觉得是「有损压缩」,担心精度掉得没法看。其实不然。好的量化策略,能把精度损失控制在 1% 以内,甚至有些场景下还能带来微弱的正则化效果,让模型更鲁棒。嗯,这里面的门道,我们慢慢聊。

量化的本质:映射与截断

量化的数学本质,就是一个映射函数。它把浮点数的取值范围,映射到整数的取值范围上。举个例子,FP32 的取值范围大约是 ±3.4×10³⁸,而 INT8 只有 -128 到 127。我们要做的,就是找到一种方式,让这个映射损失最小。

我个人习惯把量化拆成两个步骤:

  1. 确定缩放因子(Scale)和零点(Zero Point)
  2. 执行映射计算

公式其实很简单:

Q = round( (R - Z) / S )

其中 R 是原始浮点值,Q 是量化后的整数值,S 是缩放因子,Z 是零点。反过来,反量化就是:

R ≈ S × (Q - Z)

这里有个关键点:零点 Z 的存在,是为了让浮点 0 能精确映射到整数 0。为什么重要?因为卷积、全连接层里大量用到 padding 和 ReLU,如果 0 映射不准,计算就会出偏差。

对称量化 vs 非对称量化

这是量化里最基础也最核心的选择题。我直接给你对比表:

对比维度 对称量化 非对称量化
零点 Z 固定为 0 根据数据分布动态计算
映射范围 [-max, max] → [-127, 127] [min, max] → [0, 255]
计算复杂度 低(无需零点偏移) 高(需要零点偏移计算)
适用场景 权重分布对称(如正态分布) 激活值分布偏斜(如 ReLU 后)
精度损失 对非对称分布损失较大 能更好适配数据分布

对称量化,就是假设你的数据分布是对称的。权重经过训练后,通常接近零均值对称分布,所以对称量化对权重很友好。而且零点为 0,计算时少一次加减法,硬件实现更简单。

非对称量化,则更灵活。它根据实际数据的 min 和 max 来确定映射范围。比如 ReLU 后的激活值全是非负的,用非对称量化就能把整个 INT8 的 0~255 范围都用上,精度自然更高。

我的经验: 权重用对称量化,激活值用非对称量化。这是业界最成熟的方案,TensorRT、ONNX Runtime 都这么干。别自己瞎折腾,除非你有特殊需求。

量化精度与性能的权衡

为什么量化能提速?原因有三:

  • 计算更快:INT8 乘法比 FP32 快 2-4 倍,很多硬件还有专门的 INT8 指令
  • 内存更小:模型体积缩小 4 倍,缓存命中率大幅提升
  • 带宽更低:从 DDR 搬运的数据量减少,功耗自然下降

但代价是什么?精度。我直接给你看一组典型数据:

量化方案 模型体积 推理速度(FPS) 精度(Top-1)
FP32(基线) 100% 1.0x 72.5%
INT8 对称 25% 2.8x 71.8%
INT8 非对称 25% 2.6x 72.2%
INT4 12.5% 4.5x 68.3%

看到没?INT8 量化只掉了 0.3%~0.7% 的精度,但速度翻了近 3 倍。这就是量化的魅力。

我曾经踩过的坑: 有一次我把一个 MobileNetV2 直接量化到 INT8,结果精度掉了 5%。排查了半天,发现是某个层的激活值分布特别宽,量化截断把大量信息丢掉了。后来加了 校准数据集 做 KL 散度优化,才把精度拉回来。

量化精度的关键:校准与截断

校准(Calibration)是量化前必须做的一步。它的目的是:找到最佳的缩放因子 S 和零点 Z。

常见的校准方法有三种:

  1. MinMax 校准:直接用数据的 min 和 max 确定范围。简单粗暴,但对 outlier 敏感。
  2. KL 散度校准:让量化后的分布尽量接近原始分布。TensorRT 默认用这个。
  3. 百分位校准:去掉两端 1% 的极端值,减少 outlier 影响。

我个人习惯先用 MinMax 快速验证,再用 KL 散度做最终校准。如果精度还不满意,就检查一下哪些层的量化误差大,单独给它们保留 FP16。

量化推理的完整流程

下面这张图,是我在项目中总结的量化推理流程:

模型量化推理流程图 模型量化推理流程 FP32 预训练模型 校准数据集(Calibration) 统计每层激活值分布 计算 Scale / Zero Point INT8 量化推理 关键说明 • 校准集需覆盖真实场景 • 每层独立计算量化参数 • 权重用对称,激活用非对称 • 精度不达标可回退 FP16

量化精度的「黄金三角」

在实际项目中,我总结了一个「黄金三角」原则:

  • 模型结构:深度可分离卷积、残差连接对量化更友好
  • 校准数据:必须覆盖真实推理场景的分布
  • 量化策略:逐层 vs 逐通道、对称 vs 非对称

这三者缺一不可。我见过有人花了两周调量化策略,结果发现是校准集选错了——用的全是白天图片,模型一到晚上就崩。嗯,这种低级错误,犯一次就够了。

实用技巧: 量化后一定要做逐层精度对比。把每一层的输出都 dump 出来,算一下 SNR(信噪比)。哪一层 SNR 低于 30dB,就重点优化那一层。这个习惯帮我省了无数排查时间。

量化精度的「隐形杀手」

最后,我分享几个容易踩的坑:

  • BatchNorm 融合:量化前必须把 BN 层融合进 Conv 层,否则精度会崩
  • 激活函数:ReLU6 比 ReLU 对量化更友好,因为它的输出范围固定
  • 跨层连接:ResNet 的 shortcut 要注意两边的量化参数是否一致
  • 量化粒度:逐通道量化比逐层量化精度高,但计算量也大