模型量化基础:从FP32到INT8的数学原理与精度损失分析

模型量化,说白了就是给神经网络做「瘦身手术」。把原本用32位浮点数(FP32)表示的权重和激活值,换成8位整数(INT8)来存。我刚开始接触这概念时也觉得不可思议——精度降了这么多,模型还能用吗?

后来在边缘设备上跑模型时发现,FP32模型动不动就几百兆,嵌入式芯片根本塞不下。量化不是选择题,而是必答题。今天我们就把它彻底讲透。

为什么是FP32?为什么又要换成INT8?

FP32用32位二进制表示一个数,1位符号、8位指数、23位尾数。它能表示的数值范围大约是 ±3.4×10³⁸,精度约7位有效数字。训练时我们需要这个精度来稳定梯度传播。

但推理时不一样。推理只需要前向传播,对精度的容忍度其实很高。INT8只有256个离散值,但计算速度能快2-4倍,模型体积直接缩到1/4。在边缘设备上,这差距就是「能跑」和「跑不动」的区别。

核心洞察:量化不是「降级」,而是「重新编码」。我们用更少的比特,尽可能保留原始信息。关键在于找到FP32到INT8的映射关系。

量化的数学本质:仿射变换

FP32到INT8的转换,本质上是一个线性映射。公式很简单:

Q = round( (R - zero_point) / scale )

反过来,反量化:

R = Q * scale + zero_point

其中:

  • R — 原始FP32值
  • Q — 量化后的INT8值
  • scale — 缩放因子(步长)
  • zero_point — 零点偏移

scale 和 zero_point 就是我们要找的两个参数。它们决定了整个映射的质量。

对称量化 vs 非对称量化

这里有个关键选择。我个人习惯先看权重分布再决定用哪种。

类型 zero_point 适用场景 优点 缺点
对称量化 固定为0 权重(通常对称分布) 计算简单,硬件友好 浪费非对称分布的表示能力
非对称量化 根据数据计算 激活值(ReLU后全正数) 充分利用INT8的256个值 计算稍复杂

我在项目中遇到过一个问题:用对称量化去量化ReLU后的激活值,结果精度掉了3个点。因为激活值全是正数,对称量化把一半的表示范围浪费在了负数区域。换成非对称量化后,精度损失降到了0.5%以内。

经验之谈:权重用对称量化,激活值用非对称量化。这是大多数工业级部署的默认配置。

量化粒度:逐层 vs 逐通道

scale 和 zero_point 是每个张量一套,还是每个通道一套?这决定了量化粒度。

  • 逐层量化(Per-Tensor):整个层共享一组参数。计算量小,但精度损失大。
  • 逐通道量化(Per-Channel):每个输出通道独立参数。精度高,但计算稍复杂。

我建议:卷积层的权重用逐通道量化,全连接层用逐层量化就够了。卷积层不同通道的权重分布差异很大,逐通道能显著减少精度损失。

精度损失从哪来?三个罪魁祸首

量化一定会丢精度,但我们要知道丢在哪。我总结了三个主要来源:

  1. 截断误差:FP32的值超出INT8表示范围时被截断。比如scale设得太小,大数值直接溢出。
  2. 舍入误差:round()操作把连续值映射到离散整数点。这个误差最大不超过半个scale步长。
  3. 零点偏移误差:zero_point取整带来的额外偏差。非对称量化中尤其明显。

注意:量化误差会逐层累积。前面层丢1%,后面可能放大到5%。所以输入层的量化要格外小心。

量化感知训练(QAT) vs 训练后量化(PTQ)

这是两个主流方案。我直接说结论:

方法 精度 成本 适用场景
PTQ 中等(通常损失<1%) 低(只需少量校准数据) 快速部署、模型已训练好
QAT 高(损失<0.1%) 高(需要重新训练) 精度敏感、有训练资源

PTQ 适合快速验证。QAT 适合生产环境。我曾经在一个目标检测项目里,PTQ 后 mAP 掉了2.3%,换成 QAT 后只掉了0.4%。多花两天训练时间,换回2个点的精度,值。

量化误差的评估方法

怎么知道量化后模型还能不能用?我一般看三个指标:

  • 余弦相似度:比较量化前后每层输出的向量夹角。低于0.99就要警惕。
  • 信噪比(SNR):信号功率与噪声功率的比值。越高越好。
  • 最终任务指标:比如分类的Top-1准确率、检测的mAP。这是最终裁判。

嗯,这里要注意:余弦相似度高不代表最终指标好。我见过余弦相似度0.995但准确率掉了1.5%的情况。最终还是得看任务指标。

知识结构图:量化全流程

下面这张图总结了从FP32到INT8的完整流程和关键决策点:

FP32 → INT8 量化全流程 FP32 预训练模型 选择量化方案 PTQ:校准数据 + 统计 QAT:插入伪量化节点 计算 scale / zero_point 反向传播 + 微调 INT8 量化模型 精度验证:余弦相似度 / SNR / 任务指标 关键:scale 决定步长,zero_point 决定偏移

实战中的量化参数选择

最后分享几个我在项目中总结的经验:

  • 校准数据集:PTQ 时用500-1000张代表性图片就够了。别用训练集,用验证集。
  • scale 的初始化:用最大值法(max)还是 KL散度法?我推荐 KL 散度。它自动找到截断阈值,保留信息最多。
  • 特殊层处理:BatchNorm 层在量化前要融合进卷积层。不然量化误差会翻倍。
  • 量化后微调:QAT 时学习率设为原来的1/10,训练3-5个epoch就够了。多了反而过拟合。

避坑指南:我曾经在量化一个轻量级模型(MobileNetV3)时,PTQ 后精度直接崩了。后来发现是激活值分布太集中,scale 被 outlier 拉得太大。改用 percentile 方法(取99.9%分位数)后,问题解决。

量化不是玄学,是数学。理解了 scale 和 zero_point 的物理意义,你就能精准控制精度损失。下次遇到量化后模型不准,别慌,先看分布,再调参数。