3、量化基础:模型量化原理、定点与浮点表示、量化参数(scale、zero-point)、对称与非对称量化
在TinyML的工程实践中,模型量化是连接“训练好的浮点模型”与“低功耗微控制器”之间的关键桥梁。绝大多数MCU(如Cortex-M系列)不具备高效的浮点运算单元(FPU),或者为了极致功耗而刻意关闭FPU。此时,若仍以FP32精度运行神经网络,不仅推理速度慢,内存占用也会轻易击穿芯片的SRAM上限。本章将深入拆解量化的数学本质、定点与浮点数的表示差异、量化参数(scale与zero-point)的推导逻辑,以及对称/非对称两种量化策略的适用边界,为后续搭建QAT(量化感知训练)环境打下坚实的理论基础。
上图展示了量化过程中最核心的映射关系:浮点实数域通过量化参数(scale与zero-point)映射到定点整数域。理解这条链路,是掌握QAT(量化感知训练)中“伪量化”节点(FakeQuant)设计的前提。下面我们逐步拆解每个环节的数学原理与工程含义。
3.1 模型量化原理:为什么需要量化
核心原理:模型量化本质是一种信息压缩技术。它将神经网络中连续分布的浮点权重和激活值,离散化为有限数量的整数。在TinyML场景下,量化带来的收益是决定性的:
- 内存占用降低:FP32(4字节)→ INT8(1字节),模型体积直接缩小75%。例如一个1MB的模型,量化后仅需256KB。
- 计算速度提升:整数乘加运算在MCU上通常比浮点运算快4~8倍,且支持SIMD(单指令多数据)并行。
- 功耗下降:整数运算单元占芯片面积小,动态功耗显著低于浮点运算。
但量化并非无损操作。量化误差(Quantization Error)会引入噪声,极端情况下导致模型精度骤降。QAT的核心思想,就是在训练阶段模拟这种量化噪声,让模型参数在更新过程中自动适应量化误差,从而在推理时保持高精度。
3.2 定点与浮点表示:计算机眼中的数字
核心原理:浮点数(如FP32)用科学计数法表示实数,包含符号位、指数位和尾数位,动态范围大但硬件实现复杂。定点数则用固定位宽的整数表示实数,通过预先约定的缩放因子(scale)来还原真实值。
| 特性 | 浮点 (FP32) | 定点 (INT8) |
|---|---|---|
| 表示方式 | (-1)^s × 1.m × 2^(e-127) | q × scale |
| 动态范围 | 约 ±3.4×10^38 | INT8: [-128, 127] |
| 精度 | 约7位有效数字 | 均匀分布,步长固定 |
| 硬件成本 | 高(需要FPU) | 低(ALU即可) |
| 典型应用 | 训练、高精度计算 | 推理、边缘部署 |
判断方法:在TinyML中,选择定点表示的关键依据是数据分布范围。若某层激活值分布集中在[0, 1]区间,使用非对称量化可以充分利用INT8的256个离散级别;若权重分布近似高斯且关于0对称,则对称量化更合适。
3.3 量化参数:scale与zero-point的推导
核心原理:量化映射的数学表达式为:
r = s × (q - z)
其中:
r:浮点实数
q:量化后的整数
s:scale(缩放因子),浮点数
z:zero-point(零点偏移),整数
给定浮点范围 [r_min, r_max] 和量化范围 [q_min, q_max],参数推导如下:
- 计算scale:s = (r_max - r_min) / (q_max - q_min)
- 计算zero-point:z = q_min - round(r_min / s)
- 量化过程:q = clamp(round(r / s) + z, q_min, q_max)
- 反量化过程:r_hat = s × (q - z)
案例拆解:假设某层激活值统计范围为 [0.0, 6.0],采用uint8量化(q_min=0, q_max=255):
- s = (6.0 - 0.0) / (255 - 0) = 0.023529
- z = 0 - round(0.0 / 0.023529) = 0
- 若某激活值 r=3.5,则 q = round(3.5 / 0.023529) + 0 = round(148.75) = 149
- 反量化得到 r_hat = 0.023529 × (149 - 0) = 3.5059,误差约0.006
若改用int8对称量化(q_min=-128, q_max=127),且r_min=-6.0, r_max=6.0:
- s = (6.0 - (-6.0)) / (127 - (-128)) = 12.0 / 255 = 0.047059
- z = -128 - round(-6.0 / 0.047059) = -128 - (-128) = 0
- 对于r=3.5,q = round(3.5 / 0.047059) = round(74.375) = 74
- 反量化 r_hat = 0.047059 × 74 = 3.482,误差约0.018
可见,非对称量化在数据分布偏置时精度更高,但对称量化计算更简单(z=0,无需减法操作)。
3.4 对称与非对称量化:策略选择与实战对比
核心原理:对称量化强制zero-point=0,映射关系简化为 r = s × q。非对称量化则保留zero-point,允许浮点零点映射到非零整数。
| 对比维度 | 对称量化 | 非对称量化 |
|---|---|---|
| zero-point | 恒为0 | 可为任意整数 |
| 计算复杂度 | 低(无减法) | 高(需减去z) |
| 精度表现 | 分布对称时最优 | 分布偏置时更优 |
| 硬件友好度 | 高(SIMD优化容易) | 中(需额外处理) |
| 典型应用 | 权重、偏置 | 激活值、Embedding |
判断方法:对于权重,由于训练过程中权重通常被正则化到接近0对称分布,优先选择对称量化。对于激活值,经过ReLU等激活函数后往往非负(如[0, 6]),此时非对称量化能更充分利用量化范围。
3.5 案例闭环:一个语音唤醒词模型的量化策略选择
背景与约束:某智能门锁产品需部署一个关键词唤醒模型(识别“你好小锁”),目标MCU为Cortex-M4(无FPU),SRAM仅128KB,Flash 512KB。原始FP32模型大小1.2MB,推理延迟120ms,无法满足实时性要求。
初始现象:直接使用PTQ(训练后量化)将模型转为INT8后,唤醒率从95%降至82%,误唤醒率上升3倍。分析发现,模型第一层卷积的激活值分布为[0, 8.5],但PTQ默认使用对称量化,导致大量量化级别被浪费在负区间。
分析判断过程:
- 统计各层激活值分布:第一层卷积输出范围[0.2, 8.5],均值2.1;最后一层全连接输出范围[-3.2, 3.2],近似对称。
- 对比量化误差:对称量化下第一层激活值的量化噪声(SNR)为28dB,非对称量化为41dB。
- 决定采用混合策略:第一层卷积和所有ReLU后的激活层使用非对称量化;权重和全连接层使用对称量化。
实际操作步骤:
# 伪代码:在QAT中配置混合量化策略
import tensorflow as tf
quantize_config = tf.quantization.QuantizeConfig(
weight_quantizer=tf.quantization.symmetric_quantizer,
activation_quantizer=tf.quantization.asymmetric_quantizer,
# 对第一层单独设置
layer_quantizers={
'conv2d_0': tf.quantization.asymmetric_quantizer,
'dense_2': tf.quantization.symmetric_quantizer
}
)
结果对比:采用混合量化策略后,模型大小降至300KB,推理延迟降至28ms,唤醒率恢复至94.5%,误唤醒率降至0.8次/小时。代价是训练时间增加了15%(因为需要同时优化两套量化参数)。
复盘经验:量化策略的选择不能“一刀切”。在QAT中,建议先对模型做层级敏感度分析(Layer-wise Sensitivity Analysis),找出对量化误差最敏感的层,优先为其配置非对称量化。同时,zero-point的初始化值应基于校准数据集的统计值,而非简单设为0。