训练后量化需要一批代表性样本估计中间激活范围。样本只覆盖安静、正常或单一设备时,现场极端输入可能大量饱和。代表性数据集解决范围校准,无法自动修复模型对量化噪声敏感的问题。
量化感知训练在训练过程中模拟量化,让权重适应整数误差。它增加训练复杂度,应在PTQ结果经过误差定位后再使用。
| 代表性数据集负责“看见正确范围”,QAT负责“让模型适应量化误差”。两者解决的问题不同。 |
完成本篇后,你应该能够
PTQ在训练完成后选择整数尺度。代表性数据不需要标签,但必须像部署输入一样经过相同预处理并覆盖真实工况。 |
图1:PTQ优先,量化误差超出目标时再进入QAT
一、代表性数据集覆盖输入与激活范围
校准样本应覆盖正常、异常、不同设备、温度、幅值和边界工况。它不要求与训练集同样大,但不能只抽取最容易的一小批。
极端离群值可能把Scale拉得过大,降低常见范围的分辨率;缺少真实极值又会导致现场饱和。应先确认离群值是采集错误还是合法输入。
二、PTQ先提供低成本基线
训练后量化不改变原训练过程,转换速度快,适合先验证模型结构是否量化友好。比较FP32与INT8的逐样本输出、混淆矩阵和类别指标,可以判断损失集中在哪里。
若总体准确率变化很小,但某个高成本类别召回下降,仍需继续处理。平均指标可能掩盖关键类别。
Python:代表性数据生成器只输出模型真实输入
def representative_dataset(): |
三、QAT让训练适应有限整数网格
QAT在前向计算中模拟量化和反量化,反向传播仍更新浮点权重。模型可以调整权重分布,降低舍入和饱和带来的损失。
QAT需要固定量化策略、训练超参数和导出流程。它不能补救错误标签、数据泄漏或代表集缺少现场范围。
表1:PTQ与QAT的工程区别
| 方法 | 主要解决 | 使用条件 |
|---|---|---|
| PTQ | 校准范围并快速生成INT8 | 先有可靠FP32基线和代表集 |
| QAT | 让权重适应量化误差 | PTQ未达标且误差确由量化引起 |
| 重做数据 | 覆盖缺失和标签问题 | FP32本身也在关键工况失效 |
四、用明确条件决定是否进入QAT
先检查输入预处理和模型转换,再分析各层张量范围、饱和比例和类别错误。如果PTQ已达到验收指标,继续QAT只会增加维护成本。
QAT完成后重新导出INT8模型,并在同一独立测试集和目标MCU上复测效果与资源。训练图中的模拟结果不能替代最终部署模型。
代表性数据校准的不只是输入层
转换器把代表样本送入模型,观察各层激活范围并确定量化参数。只给全零或单一稳定工况,会低估某些节点范围;现场遇到更大激活时发生饱和。
代表集应覆盖设备、人员、温度、安装、类别和强弱边界,但无需复制全部训练集。每个样本必须具有真实shape、dtype和预处理,生成器一次yield一个批次。
异常极值也会拉大范围。先确认极值是真实业务输入还是采集错误。可使用更稳健校准策略,但任何裁剪都要在关键类别上验证,不能为了平均误差删除危险少数情况。
代表集覆盖检查
| 维度 | 应包含 | 缺失后果 |
|---|---|---|
| 类别 | 普通、故障、UNKNOWN边界 | 特定类激活饱和 |
| 设备 | 多器件与安装 | 换机失效 |
| 幅值 | 常见与合法极值 | 范围过窄 |
| 预处理 | 真实部署链 | 尺度完全错误 |
PTQ先做基线,QAT只在明确误差后使用
PTQ成本低,先比较FP32和INT8逐类指标、输出差异和饱和比例。若只有个别层或类别明显下降,先修代表集、输入缩放或不友好算子。
QAT在训练前向中模拟量化,使权重适应整数网格。它需要重新训练、正确冻结批归一化与量化配置,也可能过拟合。QAT目标是恢复量化损失,不能补救标签错误或跨设备数据缺失。
进入QAT前要记录基线与退出条件:例如INT8关键类召回比FP32下降超过允许值,且代表集与算子检查已通过。QAT后仍使用完全独立测试和目标板资源验证。
| 量化诊断顺序:输入范围 → 代表集覆盖 → 中间饱和 → 算子与层敏感性 → 再决定QAT。 |
五、落地检查
- 先确认FP32模型在独立测试集上达到目标。
- 代表集覆盖设备、工况、幅值和边界输入。
- 比较逐类别指标和量化前后输出差异。
- 排除预处理、算子和输入类型错误。
- 只有量化误差明确超标时才引入QAT。
动手:观察三种校准范围的量化代价
脚本生成以0为主、含少量大幅合法事件的数据,分别用稳定子集、全范围和99%分位范围校准,对测试数据统计饱和率与平均误差。
实验环境与输入
- Python 3标准库。
- 保存为 `calibration_ranges.py` 并运行。
- 这是量化范围教学,不替代转换器逐层校准。
按顺序完成实验
- 运行并比较三种范围。
- 确认稳定子集范围过窄导致高饱和。
- 增加一个错误的100倍毛刺,观察全范围分辨率下降。
- 判断毛刺应清洗、保留还是触发质量拒绝。
可直接运行:范围、饱和与误差比较
import random |
先读懂代码中的关键路径
- stable与events共同组成部署测试分布。
- 每种limit产生scale,再统计饱和率与全体MAE。
- p99允许少量裁剪换取常见范围分辨率。
- 极值是否可裁剪必须由关键类别与物理合法性决定。
你应该观察到什么
- stable_only对事件数据出现较高饱和。
- full_max饱和最低,但scale可能更大。
- p99在分辨率与少量裁剪之间折中,是否可接受由关键事件决定。
成功标准
- 代表集覆盖部署分布与预处理。
- 报告逐类效果和饱和,而非只看总体准确率。
- 只有明确量化损失且基础检查完成后才进入QAT。
失败时从哪里查起
PTQ效果下降定位
| 现象 | 原因 | 行动 |
|---|---|---|
| 常见样本也饱和 | 代表范围过窄 | 扩充真实幅值覆盖 |
| 整数码集中少数值 | 异常极值拉大scale | 核实极值来源 |
| 仅某类下降 | 该类激活分布独特 | 逐类代表集和层输出分析 |
校准集应作为正式数据资产保存样本ID与版本,确保每次转换可复现。
把实验迁移到真实MCU项目
转换器代表集应从冻结的训练样本ID读取,执行与部署相同预处理。不要在生成器里随机增强或按测试集重新归一化。
量化后在MCU记录输入饱和即可低成本监控;中间激活饱和通常在离线解释器或诊断构建中分析。
代表集的样本数量没有通用固定值。判断是否足够要看新增样本是否继续显著改变各层范围,以及关键类别和设备是否覆盖。保存校准摘要后,可以比较两次转换的scale变化,而不只比较最终准确率。
若部署包含季节、温度或多个传感器批次,代表集也要覆盖这些条件。可以按分组抽样而非只取训练数组前N条,避免文件顺序让某些设备完全缺席。校准样本ID应保存,便于转换结果复现。
量化比较要保留FP32和INT8的逐样本预测。把新增错误按真实类别、设备、输入幅值和饱和比例分组,能够判断问题来自某个工况范围还是所有样本的均匀小误差。
QAT训练完成后不要沿用PTQ代表集结论。重新导出最终模型,核对算子、I/O量化参数、文件和目标板资源;训练时的伪量化节点不等同于部署FlatBuffer。
代表集、训练集和测试集职责不同:代表集校准整数范围,训练集学习权重,测试集评价泛化。三者可以共享来源范围,但测试标签和统计不能参与尺度选择。
把结果再向前推进一步
- 按设备和类别统计代表集样本数量。
- 记录输入与关键激活的饱和比例。
- 写出触发QAT和停止QAT的明确条件。
| 这篇文章的结论代表性数据集决定PTQ校准范围,QAT让模型适应量化误差。先完成可靠PTQ基线和误差定位,再决定是否增加训练复杂度。 |
参考资料:
Google AI Edge:构建并转换微控制器模型
Google AI Edge:tf.lite API
Arm CMSIS-NN 官方文档