3、神经网络量化基础:定点数与浮点数、量化参数(scale、zero-point)、对称与非对称量化、量化精度损失来源
在进入 TinyML 的量化感知训练(QAT)之前,必须先建立扎实的数值表示基础。神经网络模型在训练时通常使用 32 位浮点数(FP32)来存储权重和激活值,但在微控制器(MCU)等边缘设备上,浮点运算单元(FPU)往往缺失或性能受限,因此需要将模型转换为定点数表示,这一过程称为量化。本章将系统梳理定点数与浮点数的本质差异、量化参数(scale 与 zero-point)的数学含义、对称与非对称量化的适用场景,以及量化过程中精度损失的四大来源。理解这些基础概念,是后续掌握 fake quant(伪量化)机制与 QAT 训练流程的前提。
上图展示了本章的核心知识框架:浮点数与定点数之间的映射关系由量化参数(scale 和 zero-point)决定,而对称/非对称量化是两种不同的映射策略,最终精度损失来源于四个主要方面。下面我们将逐一深入展开。
3.1 定点数与浮点数的本质差异
核心原理
浮点数(如 FP32)采用科学计数法表示实数,由符号位、指数位和尾数位组成,能够以极高的动态范围表示数值。例如,FP32 可以表示从 1.4e-45 到 3.4e38 的数值范围,这对于训练过程中梯度变化幅度极大的场景至关重要。然而,浮点运算需要专门的硬件单元(FPU),在 Cortex-M0 等低端 MCU 上并不存在,即使在高端的 Cortex-M7 上,浮点运算的功耗和延迟也远高于整数运算。
定点数则是将数值固定在一个有限范围内,用整数表示。以 INT8 为例,它只能表示 256 个离散值。定点数的优势在于:存储占用仅为 FP32 的 1/4,运算速度提升 2-4 倍,且无需 FPU 支持。但代价是动态范围受限,直接截断会导致严重精度损失。
判断方法
在实际工程中,判断一个张量(Tensor)是否适合定点化,需要观察其数值分布特征:
- 权重(Weights):训练收敛后权重通常分布在零附近,呈近似高斯分布,范围较小且对称,适合对称量化。
- 激活值(Activations):经过 ReLU 等激活函数后,激活值通常为非负,分布偏斜,范围较大,适合非对称量化。
- 梯度(Gradients):仅在训练时存在,推理时不需要,因此 QAT 中通常不量化梯度,但需要模拟量化误差对梯度的影响。
案例拆解
假设一个卷积层的权重范围为 [-1.5, 1.5],激活值范围为 [0.0, 6.0]。若直接使用 INT8 表示:
- 权重采用对称量化,scale = 1.5 / 127 ≈ 0.0118,zero-point = 0。
- 激活值采用非对称量化,scale = 6.0 / 255 ≈ 0.0235,zero-point = 0(因为最小值为 0)。
这种组合在 TinyML 中最为常见,既保证了权重的高精度,又覆盖了激活值的完整范围。
3.2 量化参数:scale 与 zero-point 的数学含义
核心原理
量化的数学本质是一个仿射变换(Affine Transformation)。给定浮点实数 r,量化后的整数 q 由以下公式计算:
q = round(r / scale) + zero_point
反量化(Dequantization)公式为:
r = (q - zero_point) × scale
其中:
- scale(缩放因子):浮点数,表示每个量化步长代表的实数范围。scale 越小,量化精度越高,但可表示的范围越小。
- zero-point(零点):整数,表示浮点数值 0.0 对应的量化整数。对于对称量化,zero-point 固定为 0;对于非对称量化,zero-point 通常不为 0。
计算流程
确定 scale 和 zero-point 的标准流程如下:
- 统计张量的浮点范围 [min_val, max_val]。
- 对于对称量化:scale = max(|min_val|, |max_val|) / 127(INT8 正半轴),zero-point = 0。
- 对于非对称量化:scale = (max_val - min_val) / 255,zero-point = -round(min_val / scale)。
- 量化时执行
q = clamp(round(r / scale) + zero_point, -128, 127)。
常见误区
一个常见的错误是认为 zero-point 只是为了对齐零点。实际上,zero-point 还承担着消除偏差的作用。例如,当浮点张量全为正时,若强行使用对称量化,会导致一半的量化范围(负半轴)被浪费,精度降低一半。非对称量化通过引入非零 zero-point 解决了这个问题。
3.3 对称量化与非对称量化
核心原理
对称量化要求浮点零值精确映射到整数零值,即 zero-point = 0。此时量化公式简化为 q = round(r / scale)。对称量化的优点是计算简单,在卷积运算中无需额外处理 zero-point 的偏移,适合权重和偏置的量化。
非对称量化允许 zero-point 不为 0,能够更充分地利用量化范围。对于分布严重偏斜的激活值(如 ReLU 输出),非对称量化可以显著降低量化误差。
| 对比维度 | 对称量化 | 非对称量化 |
|---|---|---|
| zero-point | 固定为 0 | 可为任意整数 |
| 计算复杂度 | 低(无需偏移修正) | 较高(需额外减法) |
| 适用场景 | 权重、偏置 | 激活值、嵌入向量 |
| 精度表现 | 数据分布对称时最优 | 数据分布偏斜时更优 |
| 硬件友好度 | 高(无需专用指令) | 中(需支持 zero-point 运算) |
判断方法
选择对称还是非对称量化,可以通过以下步骤判断:
- 绘制张量值的直方图,观察分布是否关于 0 对称。
- 若分布近似对称(如权重),优先选择对称量化。
- 若分布明显偏斜(如 ReLU 后的激活值),选择非对称量化。
- 若硬件支持非对称量化指令(如 ARM Cortex-M 的 SMMLA),则两者皆可。
案例拆解
以 MobileNetV1 的第一层卷积为例:输入图像像素值范围为 [0, 255],经过归一化后变为 [0, 1]。若采用对称量化,scale = 1/127 ≈ 0.00787,但实际数据仅占用了正半轴,负半轴完全浪费,有效精度仅为 7 bit。若采用非对称量化,scale = 1/255 ≈ 0.00392,zero-point = 0,有效精度达到 8 bit。实验表明,非对称量化在此场景下 Top-1 准确率提升约 0.8%。
3.4 量化精度损失的四大来源
核心原理
量化并非无损操作,精度损失主要来源于以下四个方面:
- 舍入误差(Rounding Error):浮点值映射到整数时,
round()操作引入的误差,最大为 0.5 × scale。 - 截断误差(Clipping Error):超出量化范围的值被截断到边界值,导致信息丢失。例如,浮点值 3.0 超出 INT8 最大表示 2.5,则被截断为 2.5。
- 范围溢出(Range Overflow):当 scale 选择过大时,虽然覆盖了全部范围,但精度降低;当 scale 过小时,大量值被截断。这是范围与精度的矛盾。
- 梯度失配(Gradient Mismatch):在 QAT 中,前向传播使用量化后的值,但反向传播的梯度需要绕过量化器(Straight-Through Estimator, STE),导致梯度与真实量化误差不完全匹配。
判断方法
定位精度损失来源的常用方法是逐层对比量化前后激活值的余弦相似度(Cosine Similarity)或均方误差(MSE):
- 运行 FP32 模型,记录每一层的输出特征图。
- 运行量化模型(或模拟量化),记录对应层的输出。
- 计算每层的 MSE,MSE 显著增大的层即为精度瓶颈。
- 检查该层的数值分布,判断是截断误差还是舍入误差主导。
案例拆解与复盘
某语音唤醒词模型在从 FP32 转换为 INT8 后,准确率从 95% 降至 82%。通过逐层分析发现:
- 第 3 层激活值范围从 [-1.2, 1.2] 变为 [0.0, 8.5],原静态校准的 scale 严重偏小,导致大量值被截断。
- 第 5 层权重分布出现长尾,对称量化导致舍入误差增大。
解决方案:
- 改用非对称量化激活值,并采用指数移动平均(EMA)动态更新 scale。
- 对权重使用 Per-Channel 量化(每输出通道独立 scale),而非 Per-Tensor 量化。
- 在 QAT 训练中增加量化噪声的强度(通过随机扰动 scale),提高模型鲁棒性。
优化后准确率恢复至 93.5%,模型大小从 2.1MB 降至 0.3MB,推理延迟从 45ms 降至 12ms(Cortex-M4 @ 80MHz)。
总结复盘
量化精度损失是不可避免的,但可以通过以下策略最小化:
- 优先使用非对称量化处理激活值,对称量化处理权重。
- 在 QAT 中模拟量化误差,让模型自适应调整。
- 使用 Per-Channel 量化提升权重精度。
- 通过校准数据集统计真实的数值范围,避免极端值主导 scale 选择。