2、量化基础:什么是量化、定点数与浮点数、线性量化公式(scale和zero-point)、对称与非对称量化

在深入TFLite后训练量化(PTQ)流程之前,必须先建立对量化核心概念的清晰认知。量化本质上是一种数值表示转换技术,它把连续或高精度的数值(通常是32位浮点数)映射到离散的低精度数值(如8位整数)。这一转换并非简单的“取整”,而是涉及数值范围分析、精度损失控制以及硬件指令集适配的系统工程。理解定点数与浮点数的本质差异、掌握线性量化公式中scale(缩放因子)与zero-point(零点)的数学含义,以及区分对称与非对称量化策略的适用场景,是后续设计校准数据集、评估模型精度损失的理论基石。

数值表示对比 FP32 浮点数 符号位1 + 指数8 + 尾数23 动态范围: ~1e-38 ~ 3.4e38 精度: 约7位有效十进制 适合训练与高精度计算 INT8 定点数 符号位1 + 数据位7 范围: -128 ~ 127 精度: 整数步长 适合推理与边缘部署 线性量化核心公式 r = S × (q - Z) r: 真实浮点值 q: 量化整数值 S: scale 缩放因子 Z: zero-point 零点 S = (rmax - rmin) / (qmax - qmin) Z = round(qmax - rmax / S) S控制步长,Z控制偏移 两者共同完成映射 量化策略对比 对称量化 Z = 0,范围对称 [-a, a] 实现简单,适合权重 无零点偏移计算 非对称量化 Z ≠ 0,范围 [min, max] 充分利用整型范围 适合激活值分布 映射 选择 量化核心:用有限的整数步长逼近浮点数值,在精度与计算效率之间取得平衡

上图展示了量化技术的三个核心维度:数值表示对比、线性量化公式以及量化策略选择。下面将逐一展开详细论述。

2.1 核心原理:从浮点数到定点数的本质跨越

浮点数(Floating-Point)采用科学计数法表示实数,由符号位、指数位和尾数位组成。以FP32为例,其内存布局为1位符号、8位指数、23位尾数,能够表示从极小到极大的动态范围。这种设计使得浮点数在训练阶段能够适应梯度值的剧烈变化,但也带来了较高的计算开销——浮点运算需要专门的ALU单元,且功耗和延迟显著高于整数运算。

定点数(Fixed-Point)则使用固定的小数点位置来表示数值。INT8定点数只有8位,范围限定在[-128, 127](有符号)或[0, 255](无符号)。虽然动态范围和精度都远不如FP32,但整数运算在硬件上极为高效:大多数CPU、GPU和NPU都针对INT8提供了SIMD加速指令,吞吐量可达FP32的2-4倍,内存带宽消耗降低75%。

量化的本质是找到一种映射关系,将浮点张量中的每个值转换为整数,同时尽可能保留原始数值的分布特征。这种映射必须满足两个条件:一是可逆性(即能从整数反推出近似浮点值),二是误差可控(即量化前后的数值差异在可接受范围内)。线性量化正是满足这两个条件的最简映射方式。

关键认知:量化不是简单的“四舍五入取整”,而是先对浮点数值范围进行缩放和平移,再执行取整操作。缩放因子S决定了整数步长代表的实际浮点大小,零点Z则确保浮点0能够被精确映射到某个整数,避免因偏移导致的系统性误差。

2.2 线性量化公式:scale与zero-point的数学推导

线性量化假设浮点值r与整数值q之间存在线性关系,其数学表达式为:

r = S × (q - Z)

其中:

  • r:原始浮点数值(如FP32激活值或权重)
  • q:量化后的整数值(如INT8)
  • S(scale):缩放因子,表示每个整数步长对应的浮点大小,计算公式为:
S = (rmax - rmin) / (qmax - qmin)
  • Z(zero-point):零点偏移,表示浮点值0对应的整数,计算公式为:
Z = round(qmax - rmax / S)

在实际应用中,校准过程首先统计浮点张量的数值范围(rmin, rmax),然后根据目标整数位宽确定(qmin, qmax)。对于INT8有符号数,qmin=-128,qmax=127;对于UINT8无符号数,qmin=0,qmax=255。TFLite默认使用INT8作为量化目标,但在某些特定场景下(如仅权重量化)也会使用UINT8。

反量化(Dequantization)操作则是将整数还原为浮点近似值:

r_approx = S × (q - Z)

这个近似值r_approx与原始r之间的差值即为量化误差。误差来源主要有两个:一是舍入误差(rounding error),由取整操作引入;二是截断误差(clipping error),当浮点值超出量化范围时被强制截断到边界值。

参数 数学含义 对精度的影响 典型取值
S(scale) 每个整数步长代表的浮点大小 S越大,步长越粗,精度越低 0.001 ~ 0.1(视数据范围而定)
Z(zero-point) 浮点0对应的整数值 Z偏移不当会导致整体偏差 通常接近0或128(UINT8)
qmin/qmax 整数表示的最小/最大值 决定可表示的浮点范围 -128/127(INT8)
rmax/rmin 浮点张量的实际数值范围 范围估计不准会引入截断误差 由校准数据集统计得出

2.3 对称与非对称量化:策略选择与适用场景

对称量化(Symmetric Quantization)要求浮点范围关于原点对称,即rmax = -rmin,此时Z恒等于0。公式简化为:

r = S × q

对称量化的优势在于:

  • 实现简单,无需存储和计算零点偏移
  • 卷积运算中无需额外的零点修正项,计算效率更高
  • 适合权重张量——权重通常分布在小范围内且近似对称

但对称量化的缺点是:如果浮点数据分布不对称(如ReLU激活函数输出全为非负值),则有一半的整数范围(负半轴)被浪费,导致有效精度降低。

非对称量化(Asymmetric Quantization)允许浮点范围不经过原点,Z可以是非零整数。它能够充分利用整个整数范围,对于分布偏斜的数据(如激活值)精度更高。代价是计算复杂度增加——在卷积或矩阵乘法中需要额外处理Z的偏移项。

在TFLite的实际部署中,通常采用混合策略:权重使用对称量化(因为权重分布相对对称且固定),激活值使用非对称量化(因为激活值分布随输入变化且常偏斜)。这种组合在精度和效率之间取得了最佳平衡。

经验法则:当浮点数据的值最大值远大于最小值时(如ReLU输出),务必使用非对称量化;当数据分布接近零对称时(如经过BatchNorm的权重),优先选择对称量化以简化计算。

2.4 案例拆解:一个卷积层的量化全过程

假设我们有一个简单的卷积层,其权重张量W的FP32数值范围为[-0.5, 0.5],激活值A(经过ReLU)的范围为[0.0, 6.0]。目标是将两者量化为INT8。

第一步:权重对称量化

W范围: rmin=-0.5, rmax=0.5
S_w = (0.5 - (-0.5)) / (127 - (-128)) = 1.0 / 255 ≈ 0.00392
Z_w = 0(对称)
量化: q_w = round(r / S_w) = round(r / 0.00392)

第二步:激活值非对称量化

A范围: rmin=0.0, rmax=6.0
S_a = (6.0 - 0.0) / (255 - 0) = 6.0 / 255 ≈ 0.02353
Z_a = round(0 - 0.0 / 0.02353) = 0
量化: q_a = round(r / 0.02353 + 0) = round(r / 0.02353)

第三步:卷积计算

原始浮点卷积:Y = W × A + b

量化后整数卷积:q_y = S_w × S_a × (q_w × q_a) + b_quantized

这里的关键在于,TFLite的量化卷积核会将S_w × S_a合并为一个缩放因子,并在累加过程中使用INT32中间精度来避免溢出,最后再缩放回INT8输出。

结果对比:假设原始浮点卷积输出某个位置为2.35,量化后反推得到的近似值为2.31,误差约1.7%。对于分类任务,这种精度损失通常不会影响Top-1准确率;但对于目标检测等对边界框回归敏感的任务,可能需要更精细的校准策略。

常见误区:不要直接使用训练集的最大/最小值作为量化范围。训练数据可能包含异常值(outliers),导致S过小、精度浪费。正确做法是使用校准数据集(通常为验证集子集)统计百分位数(如99.99%),或使用KL散度等分布匹配方法确定最优范围。

2.5 总结复盘:量化设计的核心决策点

在实际工程中,量化方案的设计需要回答以下四个问题:

  1. 位宽选择:INT8是主流选择,但极端场景下可能需要INT16(高精度需求)或INT4(极致压缩)
  2. 对称性决策:权重用对称,激活用非对称,这是TFLite的默认策略
  3. 范围确定:基于校准数据统计,而非简单取min/max
  4. 粒度选择:逐张量(per-tensor)量化实现简单,逐通道(per-channel)量化精度更高但计算更复杂