量化基础:定点与浮点表示、对称/非对称量化、量化公式推导、scale与zero-point的定义

在进入PTQ(训练后量化)的误差定位之前,必须先建立统一的量化语言。很多工程师在排查精度掉点问题时,往往直接跳到"哪个层出了问题",却忽略了最底层的表示误差——定点与浮点的映射关系、对称与非对称的选择、以及scale和zero-point的数学含义。本章将系统梳理这些基础概念,并推导出后续所有误差分析所依赖的核心公式。

数值表示 • 浮点:动态范围大,精度高 • 定点:固定步长,硬件友好 • 量化本质:浮点→定点映射 • 误差来源:舍入+截断+溢出 量化类型 • 对称:zero-point=0 • 非对称:zero-point≠0 • 权重量化:对称更常用 • 激活量化:非对称更鲁棒 核心参数 • scale:量化步长(浮点) • zero-point:零点偏移(整数) • q = round(r/scale) + zp • r = (q - zp) × scale 量化公式推导链路 浮点范围 计算scale 计算zp 量化/反量化 误差分析 对称量化:zp=0,非对称量化:zp≠0 | 误差 = 量化值 - 原始值

上图展示了量化基础知识的整体框架。从数值表示出发,区分定点与浮点的本质差异,再根据数据分布特性选择对称或非对称量化,最终落到scale与zero-point的计算与使用。这张图将贯穿本章所有内容,也是后续章节进行误差定位时的思维导图。

2.1 定点与浮点表示:量化问题的起源

核心原理

计算机中的数值表示主要分为定点(Fixed-point)和浮点(Floating-point)两种。浮点数(如FP32、FP16)通过符号位、指数位和尾数位表示,动态范围大、精度高,但硬件计算单元复杂、功耗高。定点数则使用固定的小数点位置,用整数运算模拟实数运算,硬件实现简单、速度快,但动态范围受限。

神经网络模型在训练时通常使用FP32,因为反向传播需要高精度梯度。但在推理阶段,尤其是部署到边缘设备(如手机、嵌入式设备、FPGA)时,FP32的存储和计算开销过大。量化(Quantization)的核心思想就是:将FP32的权重和激活值映射到低比特整数(如INT8、INT4),同时尽量保持模型精度。

特性浮点表示(FP32)定点表示(INT8)
动态范围约1e-38 ~ 3.4e38-128 ~ 127(有符号)
精度约7位有效数字固定步长,均匀分布
硬件成本高(需要指数对齐)低(整数ALU即可)
存储占用4字节/参数1字节/参数(4倍压缩)
适用场景训练、高精度计算推理、边缘部署

判断方法

在实际工程中,判断一个张量(Tensor)是否适合定点化,主要看三个指标:

  1. 数值分布范围:如果数据集中在很小的区间(如[-1, 1]),定点化损失较小;如果分布极不均匀(如存在长尾),则需要考虑非对称量化或更高比特。
  2. 对误差的敏感度:权重和激活的敏感度不同。通常权重的量化误差对精度影响更大,因为权重是共享的;激活的误差则逐层传递。
  3. 硬件支持:某些硬件(如NPU)对对称量化有优化指令,非对称量化可能需要额外计算。
经验提醒:在PTQ中,不要盲目将所有层都量化为INT8。先对每层做敏感性分析(如逐层量化并观察精度变化),找出"敏感层",这些层可能需要保留FP16或使用更高比特量化。

案例拆解:一个卷积层的定点化决策

假设我们有一个3x3卷积层,权重分布范围为[-0.5, 0.5],激活值分布范围为[-10, 10]。如果直接使用对称INT8量化:

  • 权重:scale = 0.5/127 ≈ 0.00394,量化误差较小。
  • 激活:scale = 10/127 ≈ 0.0787,但激活值大部分集中在[-2, 2]区间,导致小值区域的量化步长过大,相对误差高达10%以上。

这种情况下,激活使用非对称量化更合适:将[-10, 10]映射到[0, 255],scale = 20/255 ≈ 0.0784,zero-point = 128。虽然步长没有变小,但零点偏移使得小值区域也能被有效表示,减少了截断误差。

风险提示:定点化不是简单的"除以最大值再乘127"。必须考虑数据的实际分布,尤其是激活值通常呈现近似正态分布,直接使用min/max会浪费大量量化区间。

2.2 对称量化与非对称量化:如何选择

核心原理

对称量化(Symmetric Quantization)要求浮点零值精确映射到整数零值,即zero-point = 0。其映射关系为:

q = clamp(round(r / scale), -127, 127)  // INT8有符号
r = q × scale

非对称量化(Asymmetric Quantization)允许零点偏移,浮点零值映射到任意整数zero-point:

q = clamp(round(r / scale) + zero_point, 0, 255)  // INT8无符号
r = (q - zero_point) × scale

对称量化的优势在于计算简单,不需要额外处理zero-point的加减法,适合权重(通常分布关于0对称)。非对称量化则能更好地利用量化范围,适合激活值(通常分布偏向正区间)。

判断方法

维度对称量化非对称量化
zero-point固定为0可配置,通常为128(INT8)
计算复杂度低(无需偏移)高(需额外加减)
范围利用率低(若分布不对称)高(可覆盖任意分布)
硬件支持广泛(多数NPU原生支持)部分支持(需软件模拟)
典型应用权重、偏置激活值、中间特征图

案例拆解:激活值分布不对称时的量化对比

某层激活值分布为[-1, 15],均值约为3。若使用对称量化:

  • scale = 15/127 ≈ 0.118,但[-1, 0]区间只有约8个量化级别,精度严重不足。
  • 若使用非对称量化:scale = (15-(-1))/255 ≈ 0.0627,zero-point = round(-(-1)/0.0627) ≈ 16,整个范围被均匀覆盖。

实际测试中,非对称量化在该层的信噪比(SNR)比对称量化高约6dB,最终模型精度提升0.8%。

实践建议:在PTQ中,权重默认使用对称量化(因为训练好的权重通常关于0对称),激活值默认使用非对称量化(因为ReLU等激活函数导致分布偏移)。如果发现某层精度异常,优先检查该层的激活分布是否被对称量化"截断"。

2.3 量化公式推导:从浮点到定点的数学映射

核心原理

量化的本质是寻找一个映射函数 f: R → Z,将浮点数r映射到整数q,并保证反量化误差最小。标准公式为:

量化:q = clamp(round(r / scale) + zero_point, q_min, q_max)
反量化:r_hat = (q - zero_point) × scale

其中,scale(缩放因子)和zero-point(零点)是两个关键参数。推导过程如下:

  1. 确定浮点范围 [r_min, r_max] 和整数范围 [q_min, q_max]。
  2. 计算scale:scale = (r_max - r_min) / (q_max - q_min)。
  3. 计算zero-point:zero_point = q_min - round(r_min / scale)。

对于对称量化,r_min = -r_max,q_min = -q_max,则zero_point = 0。

操作流程:手动计算一个张量的scale和zero-point

假设浮点张量 r = [-2.5, -1.0, 0.0, 1.5, 3.0],目标INT8(q_min=-128, q_max=127)

1. 确定范围:r_min = -2.5, r_max = 3.0
2. 计算scale:scale = (3.0 - (-2.5)) / (127 - (-128)) = 5.5 / 255 ≈ 0.02157
3. 计算zero-point:zero_point = -128 - round(-2.5 / 0.02157) = -128 - (-116) = -12
4. 量化:q = round(r / 0.02157) + (-12)
   - r=-2.5 → round(-115.9) = -116 → q = -128
   - r=0.0 → round(0) = 0 → q = -12
   - r=3.0 → round(139.1) = 139 → q = 127
5. 反量化:r_hat = (q - (-12)) × 0.02157
   - q=-128 → r_hat = -2.502
   - q=-12 → r_hat = 0.0
   - q=127 → r_hat = 2.998

常见误区

  • 误区1:认为scale必须等于最大值/127。实际上,scale由整个范围决定,而非单点。
  • 误区2:忽略clamp操作。如果r超出[r_min, r_max],量化结果会溢出,必须截断。
  • 误区3:zero-point计算后未取整。zero-point必须是整数,否则反量化时无法精确还原零点。
关键提醒:在PTQ中,scale和zero-point的精度直接影响量化误差。通常使用FP32存储这两个参数,但在某些硬件上,scale会被进一步量化为FP16或BF16,这也会引入额外误差。

2.4 scale与zero-point的定义:误差定位的基石

核心原理

scale(缩放因子)决定了量化步长,即相邻两个整数之间的浮点距离。scale越小,量化精度越高,但需要更大的整数范围。zero-point(零点)是浮点零值在整数域中的映射,它保证了浮点零值能被精确表示,避免"零漂移"问题。

在误差定位中,scale和zero-point的异常往往是精度掉点的直接原因。例如:

  • scale过大 → 量化步长粗 → 小值被"抹平" → 激活值精度下降。
  • scale过小 → 大值溢出 → 截断误差 → 权重精度下降。
  • zero-point计算错误 → 零点偏移 → 反量化后均值偏移 → 后续层累积误差。

判断方法:如何检查scale和zero-point是否合理

检查项正常范围异常信号
scale值与数据范围同量级过大(>10×数据标准差)或过小(<0.001×标准差)
zero-point在[q_min, q_max]内超出范围或与128偏差过大(非对称时)
反量化误差相对误差 < 1%相对误差 > 5% 或出现系统性偏差
零点映射浮点0.0 → 整数zero-point浮点0.0映射后反量化不为0

案例拆解:一个scale异常导致的精度掉点排查

背景:某图像分类模型在PTQ后,Top-1精度从80.2%降至72.5%,掉点严重。

初始现象:逐层检查发现,第3个卷积层的输出特征图分布异常,大量值集中在[-0.1, 0.1]区间,但scale被计算为0.5。

分析过程:

  1. 打印该层激活值的统计信息:min=-0.08, max=0.12, mean=0.01, std=0.03。
  2. 计算理论scale:若使用非对称量化,scale = (0.12-(-0.08))/255 ≈ 0.00078。
  3. 实际scale为0.5,说明量化配置错误——可能使用了全局统计值而非该层实际分布。

解决方案:重新计算该层的scale和zero-point,使用校准数据集(Calibration Dataset)统计真实分布。修正后精度恢复至79.8%。

复盘经验:PTQ中,每层的scale必须基于该层的实际数据分布计算,不能使用全局统一值。尤其是BatchNorm层融合后,激活分布会发生变化,需要重新校准。

总结:scale和zero-point是量化的"基因",它们决定了量化误差的上限。在PTQ误差定位中,第一步永远是检查各层的scale和zero-point是否与数据分布匹配。如果发现异常,优先修正量化参数,而不是盲目调整网络结构或重新训练。