OE Agent“天工”新版本发布,请前往论坛顶部查看,欢迎试用并反馈~
查看OE-Skills
专栏算法工具链【地平线J6工具链入门教程】J6 HistogramObserver用法详解与实例

【地平线J6工具链入门教程】J6 HistogramObserver用法详解与实例

芯链情报局2026-07-03
31
0
Calibration 阶段执行 forward 时,Observer会统计张量分布,并据此计算量化所需的 scale 等参数。 不同 Observer 的统计方式和搜索策略不同,因此最终 Calibration 效果也可能存在差异。HistogramObserver 是 horizon_plugin_pytorch 量化工具中推荐的校准Observer(OE3.7.0 horizon-plugin-pytorch≥3.1.5版本开始支持HistogramObserver)。

1. HistogramObserver基础用法

HistogramObserver采用“数据分桶+动态扩展”方式统计 整个校准集 的数据分布,得到全局直方图,然后结合“搜索策略”选择合适的 scale,与其他采用“逐帧计算+滑动平均”方式的 Observer 相比,HistogramObserver在结果稳定性和精度表现上通常会更好。

有了全局直方图后,需要通过搜索策略从分布中选出最优scale。常用的搜索方式如下:

搜索方式

说明

建议

mse

默认方式。根据数据分布计算不同 scale 下伪量化前后的误差,选择损失更小的 scale。

mse大多数情况下效果较好,推荐作为首选

percentile

控制有效值在总体数据中的占比。percentile=1.0 时可理解为 minmax搜索percentile=0.9999(默认)时可轻微裁剪极端值。

作为 mse 之后的备选

HistogramObserver通常用于校准,得到最佳的校准精度,然后固定激活scale,使用速度更快的MinMaxObserver进行QAT,基于此,qconfig配置示例如下:

HistogramObserver 通常用于激活校准。相比 MinMaxObserver 等其他 Observer,使用 HistogramObserver 时,state_dict 中会多出 histogram 和 histogram_edges 两个 key,用于存放校准过程中收集的直方图统计信息(频次和 bin 边界)
如上展示了HistogramObserver的基础用法,在校准阶段采用默认mse搜索策略得到激活scale,与其它observer没有任何区别。除此之外,直方图校准具备“一次校准,多次调优”的优势,在精度表现好的基础上还可节省精度调优时重复校准的资源消耗,详情可见下一节。

2. HistogramObserver进阶用法

直方图校准具备“一次校准,多次调优”的优势主要体现在两个方面:
  1. 一次校准,复用校准结果设置不同搜索策略

  2. 一次校准,复用校准结果切换量化dtype

2.1 设置不同搜索策略

HistogramObserver在使用默认搜索方式完成 Calibration 后,如果精度不满足预期,可以通过HistogramObserver.reset_scale 接口使用其他搜索方式重新计算 scale,而无需再跑一遍校准。reset_scale定义如下:

reset_scale中每个参数含义如下:

参数

类型

作用

详细说明

cls

class

当前类本身

该函数是 @classmethod 修饰的方法,cls 表示当前类对象,而不是实例对象 self

model

torch.nn.Module

待处理模型

已经完成 calibration 的 PyTorch 模型。函数会遍历其中的 FakeQuantize 节点,重新计算 scale

method

str

scale 计算方法

指定重新计算scale 的策略。常用'mse'、'percentile'

method_kwargs

Dict

scale 计算附加参数

给 method 提供额外配置参数。用于percentile 方法,可设置:{'percentile': 0.999},表示仅保留 99.9% 数据范围用于量化。

prefix

Tuple[str]

指定处理模块范围

用于限制只对特定模块的scale 进行 reset

dtype

optional

指定量化数据类型

仅重置某种 quant dtype 的 scale。例如只处理qint8、qint16 等特定量化类型的scale。

使用建议
  • 建议优先选用默认的mse策略进行精度调优,绝大部分情况下,mse可以满足需求。

  • 切换方式:从默认 mse 改为 percentile,观察能否缓解截断或舍入误差。
  • scale 会保存在 state_dict 中,因此reset_scale后需重新保存模型权重。

使用HistogramObserver完成常规校准流程,若精度不满足预期,使用调整搜索策略进行精度调优,可基于校准后的calib_net进行如下操作:

2.2 切换量化dtype

horizon_plugin_pytorch需升级到3.3.5及以上(OE 3.9.0)

直方图校准会在整个校准集上统计全局分布并保存在模型权重中,因此完成一次 Calibration 后,可以在不重新执行校准的情况下,按精度debug分析结果调整部分节点的量化 dtype,并根据校准时统计的信息 重新计算对应节点的 scale。为此,工具链提供了 load_calib_state_dict 接口,在 QAT 或 Validation 模型前加载 Calibration 产出的 checkpoint 时,依据prepare时配置的伪量化节点 dtype 重新计算 scale。

2.2.1 load_calib_state_dict接口解析

load_calib_state_dict接口定义如下:

接口入参详解:

参数

类型

作用

详细说明

model

torch.nn.Module

目标模型

由 prepare() 生成的伪量化模型

state_dict

dict

校准模型参数字典

已完成 calibration 的模型的 state_dict,包含权重参数及 observer/fake quant 的量化统计信息(min/max、histogram、histogram_edges、scale、zero_point 等)。要求与当前 model 架构一致。

strict

bool

是否严格校验 key

默认True,存在缺失 key 或非 observer 类 unexpected key 直接报错;为 False 时允许部分 key 不匹配。

assign

bool

是否使用 assign 模式加载

透传给 torch.nn.Module.load_state_dict(assign=...)。

force_overwrite

bool

是否强制重算 scale

默认False,dtype 一致时跳过 scale 重算;为 True 时,对所有量化模块都重算 scale ,而非仅处理 dtype 不一致的模块。

reset_kwargs

Optional[dict]

scale 重计算附加参数

当 HistogramObserver 模块需要重算 scale 时,传递给 reset_scale()。例如:{'method': 'percentile', 'percentile': 0.999}。

verbose

bool

是否打印初始状态汇总

默认True,输出每个模块的 observer 类型、dtype 转换状态 汇总表。

接口返回值详解:

返回项

类型

含义

_IncompatibleKeys

namedtuple

包含 missing_keys 与 unexpected_keys,与 PyTorch load_state_dict() 返回风格一致

missing_keys

List[str]

当前模型存在但 state_dict 中缺失的参数/buffer 名称

unexpected_keys

List[str]

state_dict 中存在但当前模型没有对应项的 key(已过滤掉 activation_post_process、activation_pre_process、weight_fake_quant 相关 key)

2.2.2 支持的 dtype 切换范围

load_calib_state_dict 仅支持下列 dtype 切换:(箭头表示切换方向)
  • qint8 ↔ qint16

  • float16 ↔ float32

  • qint8/qint16 → float32

注意:无法实现qint8/qint16->float16的切换,即使通过float32间接切换也不行。因为qint8/qint16->float32时,minmax信息是空的,转float16需要有minmax信息。

2.2.3 使用流程

整体思路:先用一套相对宽松的 qconfig 完成 Calibration 并保存 state_dict,再按分析结果调整qconfig后重新 prepare 模型,最后用 load_calib_state_dict 加载校准权重。
  1. 对浮点模型float_net执行第一次 prepare 并完成 Calibration。
    1. Calibration 阶段需要在 QconfigSetter 中关闭 Conv + add 的 fuse,因为此时 conv 输入 dtype 尚未最终确定,若后续将 conv 输入改为 qint16,则无法再 fuse。Calibration 阶段不做 fuse,可兼容后续 fuse / 不 fuse 两种情况。
    2. Calibration 阶段需要在 QconfigSetter 中关闭 Gemm类算子高精度输出,否则可能会出现在修改模型尾部gemm类算子精度类型后,重新加载权重出现missing keys。
  2. 保存 calib_state_dict = calib_model.state_dict()。
  3. 在 Calibration 所用 qconfig 基础上,按敏感度分析等结果调整模板qconfig_new(例如将部分层从 qint8 提升为 qint16),对浮点模型重新 prepare,得到 qat_calib_model,可用于后续 评估精度/QAT/导出bc。
  4. 调用 load_calib_state_dict 加载 Calibration 权重,再进入 Validation 或 QAT。
注意:prepare时,FuseConvAddTemplate和OutputHighPrecisionTemplate默认是打开的。因此第一次prepare需要显式关闭,第二次prepare无需配置。

2.2.4 示例代码

如下示例可直接运行:

算法工具链
技术深度解析官方教程
评论0
0/600