量化基础:定点与浮点表示、对称/非对称量化、量化参数(scale/zero-point)与量化误差来源

在TinyML部署中,模型量化是压缩模型体积、降低内存带宽和提升推理速度的核心手段。然而,量化本质上是一个有损压缩过程,其精度损失的大小直接取决于我们对数值表示、量化参数设计以及误差传播机制的理解深度。本章将系统拆解定点与浮点数的本质差异、对称与非对称量化的适用边界、scale与zero-point的数学含义,以及量化误差的四大来源,为后续QAT(量化感知训练)调参打下坚实的理论基础。

量化核心概念与误差传播链路 浮点表示 (FP32) 符号位1 + 指数8 + 尾数23 动态范围: ±3.4×10³⁸ 精度: 约7位有效十进制 适合训练与高精度推理 定点表示 (INT8) 符号位1 + 整数7 (Q7.0) 动态范围: -128 ~ 127 精度: 整数级 适合边缘设备高效推理 量化参数 scale (s): 步长/分辨率 zero-point (z): 零点偏移 公式: q = round(r/s) + z 核心:决定映射精度与范围 对称量化 (Symmetric) z=0, 范围[-127,127] 或 [-128,127] 适合权重(分布近似对称) 非对称量化 (Asymmetric) z≠0, 范围[0,255] 或自定义 适合激活(ReLU后非负分布) 量化误差四大来源 ① 舍入误差 ② 截断误差 ③ 范围溢出 ④ 累积误差

2.1 定点与浮点表示:从数学本质到硬件代价

核心原理:浮点数(如FP32)采用科学计数法存储,由符号位、指数位和尾数位组成,能够以动态范围换取精度;定点数则使用固定的小数点位置,用整数运算模拟实数运算。在TinyML设备(如Cortex-M系列、RISC-V MCU)上,FP32运算需要专用FPU(浮点运算单元),而INT8定点运算仅需ALU(算术逻辑单元),功耗和面积可降低10-20倍。

判断方法:选择定点还是浮点,需评估三个维度:硬件能力(是否集成FPU)、实时性要求(中断延迟容忍度)、精度预算(任务允许的精度损失)。例如,语音唤醒场景通常允许5%以内的精度损失,而医疗信号监测则要求更高精度。

特性FP32浮点INT8定点INT16定点
动态范围±3.4×10³⁸-128~127-32768~32767
存储占用4字节1字节2字节
乘法器面积大(约0.1mm²)极小(约0.01mm²)小(约0.03mm²)
典型场景训练、服务器推理MCU端推理DSP端中间层
经验提醒:在ARM Cortex-M7等带FPU的MCU上,FP32推理速度可能比INT8快(因为无需反量化),但功耗和内存带宽劣势明显。实际部署前应做profiling对比,而非盲目追求低比特。

2.2 对称与非对称量化:分布匹配的艺术

核心原理:对称量化强制zero-point=0,将浮点范围[-a, a]映射到[-127, 127](或[-128,127]),计算简单且适合权重(权重分布通常关于0对称);非对称量化允许zero-point为任意整数,将浮点范围[min, max]映射到[0, 255],能更精细地利用量化区间,适合激活值(如ReLU输出恒非负)。

操作流程:选择量化类型时,先统计张量的数值分布直方图。若分布近似高斯且均值接近0,选对称;若分布偏斜或单侧集中,选非对称。对于权重,推荐对称量化;对于激活,推荐非对称量化。混合方案(权重对称+激活非对称)是工程中最常见的组合。

# 伪代码示例:对称 vs 非对称量化参数计算
def symmetric_quantize(tensor, bits=8):
    amax = max(abs(tensor.min()), abs(tensor.max()))
    scale = amax / (2**(bits-1) - 1)
    zero_point = 0
    return scale, zero_point

def asymmetric_quantize(tensor, bits=8):
    min_val = tensor.min()
    max_val = tensor.max()
    scale = (max_val - min_val) / (2**bits - 1)
    zero_point = round(-min_val / scale)
    return scale, zero_point
风险提示:非对称量化虽然精度更高,但zero-point的引入会导致推理时多一次加法运算,在部分硬件(如NPU)上可能降低吞吐量。若硬件不支持zero-point优化,应优先选择对称量化。

2.3 量化参数scale与zero-point:数学定义与校准方法

核心原理:scale(步长)决定了量化分辨率,zero-point(零点)用于对齐浮点0与整数表示。反量化公式为 r = (q - z) × s。scale越小,量化误差越小,但可表示的范围也越小;zero-point的选择直接影响量化区间的利用率。

校准流程:实际工程中,scale和zero-point通过校准数据集(通常500-1000张代表性样本)统计得出。常见方法包括:MinMax(直接取最小/最大值)、Percentile(取99.99%分位数以排除离群点)、KL散度(最小化量化前后分布差异,TensorRT采用)。

校准方法计算复杂度适用场景优缺点
MinMaxO(n)分布均匀的张量简单但易受离群点影响
PercentileO(n log n)存在长尾分布鲁棒性较好,需调分位数
KL散度O(n·bins)复杂分布(如分类层)精度最高,计算量最大
实战案例:某关键词唤醒模型在MinMax校准下精度损失达8%,改用99.9%分位数后损失降至3.2%。原因是原始激活存在少量极端值(如噪声帧),MinMax将量化范围拉宽,导致正常信号分辨率不足。通过绘制激活分布直方图,发现99.9%分位数能有效截断离群点,同时保留98%的有效动态范围。

2.4 量化误差来源:从单层到网络的累积效应

核心原理:量化误差分为四类:舍入误差(rounding,将连续值映射到离散整数时的精度损失)、截断误差(clipping,超出量化范围的值被强制截断)、范围溢出(overflow,中间计算结果超出INT8范围)、累积误差(误差在多层网络中传播放大)。其中,舍入误差是随机的,截断误差是系统性的,累积误差则与网络深度和残差结构相关。

判断方法:定位误差来源时,可逐层对比量化前后激活值的余弦相似度。若首层相似度即低于0.99,问题多出在输入分布异常;若前几层正常而后层急剧下降,则需检查是否有中间结果溢出。使用TensorBoard或Netron可视化每层的输出分布,能快速定位异常层。

  1. 舍入误差控制:采用随机舍入(stochastic rounding)替代四舍五入,在训练中引入噪声正则化。
  2. 截断误差缓解:使用百分位校准或动态范围裁剪,避免极端值主导scale。
  3. 溢出防护:在卷积层后插入clip操作,或使用INT16中间累加器(如ARM的SMLAL指令)。
  4. 累积误差抑制:在残差连接处保持浮点精度,或使用混合精度(浅层INT8,深层INT16)。
常见误区:许多工程师只关注权重量化误差,却忽略了激活值误差。实际上,激活值的动态范围更大且分布更复杂,往往是精度损失的主要来源。QAT调参时应优先关注激活值的量化参数设置。

案例复盘:某图像分类模型(ResNet-18)在PTQ(训练后量化)下精度从92%降至78%。逐层分析发现:第3层激活值范围在[-0.5, 12.3]之间,MinMax校准导致scale=0.05,而大部分激活集中在[0, 2]区间,有效分辨率仅40级。改用KL散度校准后,scale=0.02,有效分辨率提升至100级,精度恢复至89%。进一步结合QAT(仅训练3个epoch)后,精度达到91.5%,接近浮点基线。此案例说明:校准方法的选择比量化位宽更影响最终精度,且QAT能有效补偿量化误差。

总结复盘:量化参数设计应遵循"先诊断、后调参"原则。第一步,统计每层权重和激活的分布特征;第二步,根据分布选择对称/非对称和校准方法;第三步,逐层验证量化误差并定位瓶颈;第四步,针对瓶颈层实施QAT或混合精度策略。记住:没有一种量化配置适合所有模型,数据驱动的调参才是关键。