2. 量化基础
在深入TFLite后训练量化(PTQ)流程之前,必须先建立对量化核心概念的清晰认知。量化本质上是一种数值表示转换技术,它把连续或高精度的数值(通常是32位浮点数)映射到离散的低精度数值(如8位整数)。这一转换并非简单的“取整”,而是涉及数值范围分析、精度损失控制以及硬件指令集适配的系统工程。理解定点数与浮点数的本质差异、掌握线性量化公式中scale(缩放因子)与zero-point(零点)的数学含义,以及区分对称与非对称量化策略的适用场景,是后续设计校准数据集、评估模型精度损失的理论基石。
上图展示了量化技术的三个核心维度:数值表示对比、线性量化公式以及量化策略选择。下面将逐一展开详细论述。
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 总结复盘:量化设计的核心决策点
在实际工程中,量化方案的设计需要回答以下四个问题:
- 位宽选择:INT8是主流选择,但极端场景下可能需要INT16(高精度需求)或INT4(极致压缩)
- 对称性决策:权重用对称,激活用非对称,这是TFLite的默认策略
- 范围确定:基于校准数据统计,而非简单取min/max
- 粒度选择:逐张量(per-tensor)量化实现简单,逐通道(per-channel)量化精度更高但计算更复杂