2、量化基础:数值表示、定点与浮点、线性量化原理、对称与非对称量化

在进入 TensorFlow Lite 的 PTQ(训练后量化)与 QAT(量化感知训练)之前,必须先建立扎实的数值表示与量化数学基础。量化本质上是用有限精度的离散数值去逼近连续(或高精度)的实数张量,其核心矛盾在于:表示范围与表示精度之间的权衡。本章将从计算机数值表示出发,逐步推导线性量化的数学原理,并深入对比对称与非对称两种量化方案,为后续 INT8 部署与 Calibration 报告解读提供理论支撑。

数值表示 线性量化核心 对称 vs 非对称 浮点 (FP32/FP16/BF16) 符号位 + 指数 + 尾数 定点 (INT8/INT16) 符号位 + 整数位 + 小数位 动态范围 FP32: ~1e-38 到 ~3.4e38 精度分布 浮点非均匀,定点均匀 量化 = 浮点 → 定点映射 仿射变换 r = S × (q - Z) 缩放因子 S S = (rmax - rmin) / (qmax - qmin) 零点 Z Z = round(qmin - rmin / S) 量化误差 舍入误差 + 截断误差 Calibration 确定 S 和 Z 对称量化 Z = 0,范围 [-127, 127] 非对称量化 Z ≠ 0,范围 [0, 255] 适用场景 对称:权重;非对称:激活 精度对比 非对称多1bit有效精度 TFLite 默认:权重对称,激活非对称 图:量化基础概念关系图 — 从数值表示到线性量化再到对称/非对称选择

2.1 数值表示:浮点与定点的本质差异

计算机中数值的二进制表示方式直接决定了量化的可行性与精度损失程度。浮点数(Floating-Point)采用科学计数法存储,由符号位、指数位和尾数位组成。以 FP32 为例,其 32 位被划分为 1 位符号、8 位指数和 23 位尾数,能够表示约 1e-38 到 3.4e38 的动态范围,且数值分布呈非均匀特性——越靠近零,可表示的精度越高。这种设计非常适合神经网络训练阶段,因为梯度更新通常需要跨越多个数量级。

定点数(Fixed-Point)则完全不同,它使用固定的整数位和小数位来表示数值。例如 Q7.8 格式表示 7 位整数和 8 位小数。定点数的动态范围远小于浮点数,但其优势在于硬件实现简单、计算速度快、功耗低。在嵌入式设备上,INT8 定点运算比 FP32 浮点运算快 2-4 倍,内存占用减少 75%。

关键认知:量化不是简单的“四舍五入”,而是将浮点张量映射到定点整数域的过程。这个映射必须保证:① 原始数据的分布特征尽量保留;② 映射后的整数能覆盖原始数据的动态范围;③ 反量化后能近似还原原始数值。

2.2 线性量化原理:从仿射变换到实际计算

线性量化(Linear Quantization)是最常用的量化方案,其数学本质是一个仿射变换。给定浮点实数 r,量化后的整数 q 满足:

r = S × (q - Z)

其中,S 是缩放因子(Scale),Z 是零点(Zero Point)。S 的计算公式为:

S = (rmax - rmin) / (qmax - qmin)

Z 的计算公式为:

Z = round(qmin - rmin / S)

实际量化过程分为两步:首先将浮点值除以 S 并加上 Z,然后进行四舍五入取整。反量化则是将整数 q 减去 Z 再乘以 S。这种线性映射的优点是计算开销极小,适合在边缘设备上高效执行。

参数 符号 含义 典型值(INT8)
缩放因子 S 每个量化步长代表的浮点范围 0.001 ~ 0.1
零点 Z 浮点 0 对应的量化整数值 0(对称)或 128(非对称)
量化范围 [qmin, qmax] 整数表示的最小/最大值 [-128, 127] 或 [0, 255]
浮点范围 [rmin, rmax] 原始张量的最小/最大值 由 Calibration 确定

2.3 对称量化与非对称量化:原理与选择

对称量化(Symmetric Quantization)要求零点 Z = 0,即浮点 0 映射到整数 0。此时量化公式简化为 r = S × q。对称量化的优势在于实现简单,无需存储零点,且卷积运算中的乘加操作可以避免额外的偏移计算。其缺点是当数据分布偏向正数或负数一侧时,动态范围利用率不足。例如,若激活值范围为 [0, 6],对称量化会将其映射到 [-128, 127],导致一半的量化区间被浪费。

非对称量化(Asymmetric Quantization)允许 Z ≠ 0,能够充分利用整个整数范围。对于上述 [0, 6] 的激活值,非对称量化可将其映射到 [0, 255],精度提升约一倍。TensorFlow Lite 的默认策略是:权重使用对称量化,激活使用非对称量化。这是因为权重通常关于 0 对称分布,而激活值经过 ReLU 后往往非负。

工程经验:在 TFLite 中,如果你发现某层激活值分布极度偏斜(例如全为正),使用非对称量化可显著降低精度损失。但非对称量化在推理时需要额外处理零点偏移,会增加少量计算开销。对于卷积层,通常建议权重对称、激活非对称;对于全连接层,两者均可。

2.4 量化误差分析与 Calibration 的关系

量化误差主要来源于两个方面:舍入误差(Rounding Error)和截断误差(Clipping Error)。舍入误差是量化取整时不可避免的,其最大值为 S/2。截断误差则发生在浮点值超出 [rmin, rmax] 范围时,这些值会被强制截断到边界。Calibration(校准)过程的核心任务就是确定最优的 [rmin, rmax],以最小化总体误差。

常见的 Calibration 方法包括:

  1. MinMax 校准:直接使用张量的实际最小/最大值,简单但易受异常值影响。
  2. Percentile 校准:截取分布的某个百分位(如 99.9%),去除极端离群点。
  3. KL 散度校准:通过最小化量化前后分布的 KL 散度来选择阈值,是 TFLite 默认方法。
  4. MSE 校准:最小化量化前后张量的均方误差。
常见误区:很多开发者误以为 Calibration 数据集越大越好。实际上,Calibration 数据应具有代表性而非数量多。使用 100 张与训练集分布一致的图片通常比 1000 张随机图片效果更好。此外,Calibration 时应关闭 BatchNorm 的更新,保持模型在推理模式。

2.5 案例拆解:一个 Conv2D 层的量化全过程

假设我们有一个 Conv2D 层,其权重张量 W 的浮点范围为 [-1.5, 2.0],激活值 A 的范围为 [0.0, 5.0]。我们使用 INT8 量化,权重采用对称量化,激活采用非对称量化。

步骤 1:权重量化(对称)

S_w = (2.0 - (-1.5)) / (127 - (-128)) = 3.5 / 255 ≈ 0.01373
Z_w = 0
量化权重:q_w = round(r_w / S_w)

步骤 2:激活量化(非对称)

S_a = (5.0 - 0.0) / (255 - 0) = 5.0 / 255 ≈ 0.01961
Z_a = round(0 - 0.0 / 0.01961) = 0
量化激活:q_a = round(r_a / S_a + Z_a)

步骤 3:卷积计算。在 INT8 域中执行卷积,累加结果使用 INT32 存储以避免溢出。最终输出需反量化回浮点:

r_out = S_w × S_a × (q_out - Z_a)

结果对比:使用 1000 张验证集图片测试,FP32 模型 Top-1 准确率为 92.3%,INT8 量化后为 91.8%,精度损失仅 0.5%。若改用 MinMax 校准而非 KL 散度,精度损失会增大到 1.2%,因为激活值中存在少量离群点。

复盘经验:该案例表明,对于权重分布相对均匀的层,对称量化足够;而激活值由于 ReLU 的存在,非对称量化能更好地保留信息。Calibration 方法的选择对最终精度有显著影响,KL 散度方法在大多数视觉模型中表现稳定。

2.6 总结与常见误区

本章的核心要点可归纳为:量化是浮点到定点的线性映射,S 和 Z 是核心参数;对称量化适合权重,非对称量化适合激活;Calibration 决定了 S 和 Z 的质量,直接影响模型精度。在实际工程中,务必注意以下误区:

  • 误区一:认为 INT8 量化必然导致精度大幅下降。实际上,通过合理的 Calibration 和逐层误差分析,大多数模型精度损失可控制在 1% 以内。
  • 误区二:忽略零点 Z 的存在。在非对称量化中,Z 的微小误差会在多层累积后放大。
  • 误区三:对所有层使用相同的量化配置。不同层的数据分布差异很大,应分别设置对称/非对称模式。
  • 误区四:Calibration 数据集与训练集分布不一致。这会导致 S 和 Z 偏离真实分布,量化后精度骤降。

理解这些基础原理后,下一阶段我们将深入 PTQ 的具体流程,包括如何选择合适的 Calibration 方法、如何解读 Calibration 报告中的直方图与误差指标,以及如何在 TensorFlow Lite 中配置量化参数。