QConfig 的定义
qconfig(Quantization Configuration)指的是量化配置,是深度学习模型量化过程中的关键参数集合,模型的量化方式由 qconfig 决定,在准备 qat / calibration 模型之前,需要先给模型设置 qconfig。
关于qconfig的详细原理,您可以参考 构建QConfig 章节的内容。
使用 QconfigSetter 配置qconfig (推荐)
在实际的大模型或复杂网络中,手动为每个层设置 QConfig 非常繁琐。
QconfigSetter 配合 模板 (Templates) 可以根据计算图自动分发配置。
QconfigSetter 依赖于 prepare 阶段生成的计算图(Graph Mode),它按照模板列表 (templates) 的顺序依次应用规则。
QconfigSetter 的核心结构如下:
QconfigSetter(
reference_qconfig=..., # 1. 提供基础的 `observer` 的qconfig
templates=[...], # 2. 核心:配置规则列表 (按顺序生效)
enable_optimize=True, # 3. if True, 自动开启图优化
save_dir=... # 4. qconfig 配置结果(qconfig.pt 文件)和 changelog 的保存路径
custom_qconfig_mapping=... # 5. 用字典为单算子指定自定义的qconfig.
)
reference_qconfig 设置
我们推荐使用 get_qconfig 快速配置reference_qconfig, 参考示例如下:
import torch
from horizon_plugin_pytorch.quantization import get_qconfig
from horizon_plugin_pytorch.quantization.observer_v2 import MinMaxObserver
from horizon_plugin_pytorch.quantization.qconfig import QConfig
from horizon_plugin_pytorch.quantization.fake_quantize import FakeQuantize
from horizon_plugin_pytorch.dtype import qint8
reference_qconfig = get_qconfig(
observer=MinMaxObserver, # 输入输出 observer 类型,只支持 horizon_plugin_pytorch.quantization.observer_v2 中的 MinMaxObserver 和 MSEObserver,默认值为 MinMaxObserver。
in_dtype=None, # 输入数据类型,考虑算子的支持情况进行设置。None 表示 QConfig 的 input 关键字为 None,默认值为 None。
weight_dtype=qint8, # 权重数据类型,考虑算子的支持情况进行设置。None 表示 QConfig 的 weight 关键字为 None,默认值为 qint8。
out_dtype=qint8, # 输出数据类型,考虑算子的支持情况进行设置。None 表示 QConfig 的 output 关键字为 None,默认值为 qint8。
fix_scale=True, # 是否固定输入输出 scale。
)
qconfig配置模板 (Templates)
模板按列表顺序生效,后定义的模板会覆盖先定义的配置(或者特定名称覆盖全局),更详细的解释可以查看 构建QConfig 章节。
常用模板包括:
-
ModuleNameTemplate (通用): 通过算子名称或前缀设置 dtype。
"": dtype 表示全局默认配置, 越长的名字(越具体)优先级越高。支持设置固定阈值 (threshold)。
-
ConvDtypeTemplate: 专门用于批量设置卷积层的 input 和 weight 类型。
-
MatmulDtypeTemplate: 专门用于批量设置矩阵乘法(Linear/MatMul)的 input 类型。
-
SensitivityTemplate: 根据敏感度分析结果,自动将 Top-N 的敏感层设置为高精度。
-
LoadFromFileTemplate: 加载 qconfig.pt 文件,用于复现之前的量化配置。此时 enable_optimize 必须为 False,否则配置结果的正确性无法保证,部署时可能存在 cpu 算子。
一个常用的模板配置例子为:
import torch
import copy
import os
from horizon_plugin_pytorch.dtype import qint8, qint16
from horizon_plugin_pytorch.quantization import get_qconfig, observer_v2, prepare, PrepareMethod
from horizon_plugin_pytorch.quantization.qconfig_setter import (
ConvDtypeTemplate,
MatmulDtypeTemplate,
ModuleNameTemplate,
QconfigSetter,
)
# 1. 定义配置模板 (Templates)
# 这里的顺序非常重要:
# 先设置全局为 Float16,然后用具体的 Conv/Matmul 配置去覆盖它。
q_template = [
# [策略1] 全局兜底:所有算子默认输出 Float16 (模拟伪转换)
ModuleNameTemplate({"": torch.float16}),
# [策略2] MatMul:将所有 MatMul 算子的输入强制设为 Int16
MatmulDtypeTemplate(
input_dtypes=[qint16, qint16],
),
# [策略3] Conv:输入 Int16 (保精度), 权重 Int8
ConvDtypeTemplate(
input_dtype=qint16,
weight_dtype=qint8,
),
]
配置custom qconfig
尽管qconfig模板已经可以覆盖大部分的模型qconfig配置需求,但考虑到可能存在一些特殊场景,我们也在 QconfigSetter 中提供了接口,支持您为模型算子单独配置qconfig 。
首先,您可以直接配置qconfig, 一个 qconfig 对象可以设置 input / weight / output 三个关键字,分别表示算子输入/权重/输出的量化配置.
prepare 模型时会根据这些配置决定是否要在对应位置插入 FakeQuantize / FakeCast 节点,None 表示不插入任何节点。
FakeQuantize 是伪量化节点,会对输入进行量化反量化操作,插入伪量化可以在浮点模型的前向中模拟量化产生的误差,主要用于定点类型算子的量化, 例如 qint8 和 qint16 。
FakeCast 是伪转换节点,会将输入转换为 float32 类型,如果数据类型是 float16,那么还会在中间模拟转 float16 产生的截断误差,此节点主要用于标志需要浮点计算的算子。
一个 Qconfig 定义的例子是:
import torch
from horizon_plugin_pytorch.quantization.qconfig import QConfig
from horizon_plugin_pytorch.quantization.fake_quantize import FakeQuantize
from horizon_plugin_pytorch.quantization.fake_cast import FakeCast
from horizon_plugin_pytorch.quantization.observer_v2 import MinMaxObserver
from horizon_plugin_pytorch.dtype import qint8
qconfig = QConfig(
input=None,
weight=FakeQuantize.with_args(
observer=MinMaxObserver,
dtype=qint8,
qscheme=torch.per_channel_symmetric,
ch_axis=0,
),
output=FakeCast.with_args(dtype=torch.float16),
# activation=xxx 早期用法,作用与 output 关键字一致,当前仍兼容,但建议您使用 output 关键字。
)
这个 qconfig 定义了 weight类型为 per-channel 对称量化,类型为 qint8 , observer 为 MinMaxObserver 。
有了qconfig, 您可以用 custom_qconfig_mapping 为模型单算子指定qconfig:
qconfig_mapping={
"module_name": qconfig
}
QconfigSetter(
reference_qconfig=...,
templates=[...],
enable_optimize=True,
save_dir=...
custom_qconfig_mapping=qconfig_mapping
)
综上,您可以对模型的 qconfig 实现完全的控制。