量化基础:定点与浮点表示、对称/非对称量化、量化参数(scale/zero-point)与量化误差来源
在TinyML部署中,模型量化是压缩模型体积、降低内存带宽和提升推理速度的核心手段。然而,量化本质上是一个有损压缩过程,其精度损失的大小直接取决于我们对数值表示、量化参数设计以及误差传播机制的理解深度。本章将系统拆解定点与浮点数的本质差异、对称与非对称量化的适用边界、scale与zero-point的数学含义,以及量化误差的四大来源,为后续QAT(量化感知训练)调参打下坚实的理论基础。
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端中间层 |
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
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采用)。
| 校准方法 | 计算复杂度 | 适用场景 | 优缺点 |
|---|---|---|---|
| MinMax | O(n) | 分布均匀的张量 | 简单但易受离群点影响 |
| Percentile | O(n log n) | 存在长尾分布 | 鲁棒性较好,需调分位数 |
| KL散度 | O(n·bins) | 复杂分布(如分类层) | 精度最高,计算量最大 |
2.4 量化误差来源:从单层到网络的累积效应
核心原理:量化误差分为四类:舍入误差(rounding,将连续值映射到离散整数时的精度损失)、截断误差(clipping,超出量化范围的值被强制截断)、范围溢出(overflow,中间计算结果超出INT8范围)、累积误差(误差在多层网络中传播放大)。其中,舍入误差是随机的,截断误差是系统性的,累积误差则与网络深度和残差结构相关。
判断方法:定位误差来源时,可逐层对比量化前后激活值的余弦相似度。若首层相似度即低于0.99,问题多出在输入分布异常;若前几层正常而后层急剧下降,则需检查是否有中间结果溢出。使用TensorBoard或Netron可视化每层的输出分布,能快速定位异常层。
- 舍入误差控制:采用随机舍入(stochastic rounding)替代四舍五入,在训练中引入噪声正则化。
- 截断误差缓解:使用百分位校准或动态范围裁剪,避免极端值主导scale。
- 溢出防护:在卷积层后插入clip操作,或使用INT16中间累加器(如ARM的SMLAL指令)。
- 累积误差抑制:在残差连接处保持浮点精度,或使用混合精度(浅层INT8,深层INT16)。
案例复盘:某图像分类模型(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能有效补偿量化误差。