征程6校准量化中HistogramObserver原理解析
时间:2026-08-12 | 作者:星际追番人 | 阅读:01. HistogramObserver的定义与原理
HistogramObserver是horizon_plugin_pytorch中一种基于直方图统计的量化Observer。
与MinMaxObserver仅记录最小最大值、MSEObserver在线性搜索中计算MSE不同,HistogramObserver通过构建完整的数值分布直方图来捕获张量的统计特性,并支持多种量化参数计算方法。
1.1 基本原理
HistogramObserver的工作流程分为两个阶段:
阶段一:直方图收集(forward过程)
对于每个输入张量 x:1. 计算当前batch的min_val_cur, max_val_cur2. 初始化或扩展直方图边界: - 首次初始化:以max(|min|, |max|)为基准,扩展到最近的2的幂次 - 后续扩展:当数值超出当前边界时,边界按2倍扩展3. 将数值映射到直方图桶中,累加到全局直方图
阶段二:量化参数计算(calculate_qparams过程)
HistogramObserver支持多种计算方法,在calculate_qparams时根据method参数选择:
| 方法 | 描述 |
|---|---|
| mse | 最小化量化误差的积分估计(默认) |
| kl | 最小化KL散度 |
| js | 最小化JS散度 |
| cdf_kl | 基于累积分布函数的KL散度 |
| cdf_js | 基于累积分布函数的JS散度 |
| wasserstein | 最小化Wasserstein距离 |
| percentile | 百分位截断 |
重点关注mse 和 percentile 即可。
1.2 核心实现
def forward(self, x_orig):x = x_orig.detach().to(self.min_val.dtype)# 计算当前batch的min/maxmin_val_cur, max_val_cur = torch.aminmax(x, dim=1)# 初始化直方图边界(首次)if self.histogram_edges.numel() == 0:max_abs = torch.maximum(-min_val_cur, max_val_cur)max_abs = 2 ** torch.ceil(torch.log2(max_abs))# 对齐到2的幂次self.histogram_edges = ...# 扩展边界(当数值超出范围时)if need_update_hist.any():multiple = 2 ** torch.ceil(torch.log2(...))self.histogram_edges[idx] *= multiple# 累加当前batch的直方图bin_idx = vmap(self.bucketize_per_sample)(x, self.histogram_edges)self.histogram += hist
1.3 直方图扩展机制
当遇到超出当前边界的数值时,边界会按2的幂次扩展。
同时,通过分桶合并保持bin数量不变:
# 边界扩展倍数multiple = 2 ** torch.ceil(torch.log2(ratio))# 重构直方图:将原直方图的bins合并到新范围new_hist[slice_start:slice_end] = padded_histogram.reshape(-1, multiple).sum(dim=-1)
这种设计确保了以下几点:
直方图可以处理任意范围的数值
内存占用保持恒定
多卡校准结果一致性
1.4 特点分析
优点:
保留完整分布信息,支持多种量化参数计算方法
计算与收集分离,可在校准后灵活切换方法
边界对齐机制确保多卡校准结果一致
缺点:
内存占用较高(bin_num默认2048)
2. 与MinMaxObserver/MSEObserver的区别
2.1 核心差异对比
| 特性 | MinMaxObserver | MSEObserver | HistogramObserver |
|---|---|---|---|
| 统计方式 | 仅记录min/max | 在线搜索最优scale | 构建完整直方图 |
| 内存占用 | 极低 | 中等 | 较高 |
| 计算时机 | forward时更新 | forward时搜索 | forward收集,qparams时计算 |
| 分布感知 | 否 | 部分(通过MSE) | 是(完整分布) |
| 多方法支持 | 否 | 否(仅MSE) | 是(7种方法) |
| Per-channel支持 | 是 | 是 | 是 |
2.2 具体区别分析
与MinMaxObserver的区别:
信息保留:MinMaxObserver只保留极值信息,丢失了分布密度;HistogramObserver保留完整分布信息。
离群值处理:MinMaxObserver对离群值极其敏感;HistogramObserver通过分布感知方法(如percentile、kl)自动处理离群值。
校准稳定性:MinMaxObserver的滑动平均可能导致校准结果不稳定;HistogramObserver的直方图累加更加稳定。
与MSEObserver的区别:
计算时机:MSEObserver在每次forward时进行完整的搜索;HistogramObserver将收集和计算分离。
误差度量:MSEObserver仅支持L2误差;HistogramObserver支持MSE、KL、JS、Wasserstein等多种度量。
灵活性:HistogramObserver支持在计算量化参数时更换方法,无需重新校准。
3. reset_dtype与reset_scale用法
3.1 reset_dtype方法
reset_dtype方法定义在ObserverBase基类中,用于在运行时更改量化数据类型:
def reset_dtype(self, dtype):dtype = get_horizon_quant_dtype(dtype)if dtype == self.dtype:returnself.dtype = dtypeself._set_quant_min_max(self.dtype)
使用场景:
混合精度量化:不同层使用不同量化位宽时,动态调整Observer的dtype。
量化位宽探索:尝试INT8、INT4等不同位宽,无需重新校准。
from horizon_plugin_pytorch.dtype import qint8, qint4observer = HistogramObserver(dtype=qint8)# 校准完成后,尝试INT16量化observer.reset_dtype(qint16)scale, zero_point = observer.calculate_qparams()
3.2 reset_scale类方法
reset_scale是HistogramObserver的类方法。
它用于基于已收集的直方图重新计算量化参数:
def reset_scale(cls,model: torch.nn.Module,method: str,method_kwargs: Dict = None,prefix: Tuple[str] = None,dtype=None,):for n, m in model.named_modules():if isinstance(m, FakeQuantizeBase) and isinstance(getattr(m, "activation_post_process", None), cls):m.set_qparams(m.activation_post_process.calculate_qparams(m.get_dtype(), method, **method_kwargs)[0])
这里的参数可以这样理解:
| 参数 | 说明 |
|---|---|
| model | 待处理的模型 |
| method | 计算方法:mse/kl/js/cdf_kl/cdf_js/wasserstein/percentile |
| method_kwargs | 方法参数(如steps、percentile) |
| prefix | 仅处理指定前缀的模块 |
| dtype | 仅处理指定dtype的模块 |
使用场景:
方法对比实验:使用同一份校准数据,对比不同量化参数计算方法的效果。
# 对比不同方法methods = ['mse', 'kl', 'wasserstein', 'percentile']for method in methods:HistogramObserver.reset_scale(model, method)evaluate(model)
混合策略量化:不同层使用不同的校准方法。
# Attention层更适合用KL方法HistogramObserver.reset_scale(model, method='kl', prefix='model.layers.0.self_attn')# FFN层则使用MSE方法HistogramObserver.reset_scale(model, method='mse', prefix='model.layers.0.mlp')
3.3 reset_scale vs 重新校准
| 对比项 | reset_scale | 重新校准 |
|---|---|---|
| 数据需求 | 不依赖校准数据 | 需要准备校准数据 |
| 时间成本 | 非常低 | 相对较高 |
| 适用场景 | 适合做方法对比、参数调优 | 更适合分布变化或数据更新后的场景 |
4. 使用场景建议
from horizon_plugin_pytorch.quantization.observer_v2 import HistogramObserverfrom horizon_plugin_pytorch.quantization.qconfig import QConfigfrom horizon_plugin_pytorch.quantization.fake_quantize import FakeQuantize# 高精度量化场景qconfig = QConfig(weight=FakeQuantize.with_args(observer=HistogramObserver,dtype=qint8,bin_num=2048,),output=FakeQuantize.with_args(observer=HistogramObserver,dtype=qint8,bin_num=2048,),)# 完成校准后,再切换不同方法做测试for method in ['mse', 'kl']:HistogramObserver.reset_scale(model, method)acc = evaluate(model)
方法选择建议:
| 数据分布特征 | 推荐方法 |
|---|---|
| 正态分布 | mse |
| 长尾分布 | percentile 或 kl |
| 多峰分布 | wasserstein |
| 存在离群值 | percentile(0.9999) |
HistogramObserver在实际应用中,适用于以下场景:
高精度量化需求
复杂分布数据
需要灵活调整量化策略的场景
建议:校准时收集直方图,通过reset_scale对比不同方法后确定最优策略。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
