快捷键

torch.ao.quantization.qconfig 的源代码

# mypy: 允许未类型化定义
导入 复制
导入 警告
from 集合 导入 命名元组
from 打字 导入 任何, 可选, 联合
from typing_extensions 导入 已弃用

导入 火炬
导入 torch.nn  神经网络
from torch.ao.quantization.fake_quantize 导入 (
    默认动态 fake_quant,
    默认嵌入伪量化,
    默认嵌入伪量化 4 位,
    默认伪量化,
    默认融合激活伪量化,
    默认融合通道权重假量化,
    默认融合权重假量化,
    默认通道权重假量化,
    默认权重假量化,
    伪量化,
    模拟量化基类,
    熔合通道权重伪量化范围-127 到 127,
    熔合权重伪量化范围-127 到 127,
    熔合移动平均观测伪量化,
)

from .观察者 导入 (
    部分包装器,
    默认调试观察者,
    默认动态量化观察者,
    默认浮点 Q 参数观察者,
    默认浮点 Q 参数观察者 4 位,
    默认观察者,
    默认通道权重观察者,
    默认占位符观察者,
    默认重用输入观察者,
    默认权重观察者,
    直方图观察者,
    最小最大观察者,
    移动平均最小最大观察者,
    空操作观察者,
    观察者基类,
    每通道权重观察者范围-127 到 127,
    占位符观察者,
    ReuseInputObserver,
    weight_observer_range_neg_127_to_127,
)


全部 = [
    "Q 配置",
    # TODO: 已弃用,请删除
    "Q 配置动态",
    "default_qconfig",
    "默认调试 qconfig",
    "默认按通道 qconfig",
    "默认动态 qconfig",
    "float16 动态 qconfig",
    "float16 静态 qconfig",
    "按通道动态 qconfig",
    "浮点 qparams 仅权重 qconfig",
    "浮点 qparams 仅权重 qconfig_4bit",
    "默认 quint8 权重 qconfig",
    "默认 qat_qconfig",
    "默认动态 qat_qconfig",
    "默认仅权重 qconfig",
    "默认激活仅 Qconfig",
    "默认 QAT Qconfig v2",
    "默认重用输入 Qconfig",
    "默认对称 Qnnpack Qconfig",
    "默认_per_channel 对称_qnnpack_qconfig",
    "默认对称_qnnpack_qat_qconfig",
    "默认_per_channel 对称_qnnpack_qat_qconfig",
    "默认嵌入_qat_qconfig",
    默认嵌入量化 QAT 配置 4 位,
    "获取默认 Qconfig",
    "获取默认 QAT Qconfig",
    "获取默认 Qconfig 字典",
    "获取默认 QAT Qconfig 字典",
    "Q 配置任意",
    "qconfig 等于",
]


[文档]class QConfig(namedtuple("QConfig", ["activation", "weight"])): ```python # 假设输入文本为: input_text = '"""' # 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API) def translate_to_simplified_chinese(text): # 这里应该调用真实的翻译 API 进行翻译 # 由于示例中不使用真实的 API,以下为模拟翻译结果 return text # 输出翻译结果 translated_text = translate_to_simplified_chinese(input_text) print(translated_text) ``` 描述了如何通过提供来量化一个层或网络的一部分 激活和权重分别的设置(观察器类) 注意,QConfig 需要包含观察器 **类**(如 MinMaxObserver)或一个在调用时返回实例的可调用对象。 量化准备函数将为每一层的每个观察器实例化多次。 量化准备函数将为每一层的每个观察器实例化多次。 观察者类通常具有合理的默认参数,但可以使用 `with_args` 进行覆盖 方法(行为类似于 functools.partial):: my_qconfig = QConfig( 激活=MinMaxObserver.with_args(dtype=torch.qint8), weight=default_observer.with_args(dtype=torch.qint8)) """ __slots__ = () def __new__(cls, activation, weight): 捕捉常见错误 如果 isinstance(activation, nn.Module) 或 isinstance(weight, nn.Module): raise ValueError( "QConfig 接收了观察者实例,请传递观察者类。" 使用 `MyObserver.with_args(x=1)` 来覆盖构造函数的参数(如有需要) ) 返回 super().__new__(cls, activation, weight)
@deprecated( `QConfigDynamic` 将在 PyTorch 1.12 中被弃用,请使用 `QConfig` 代替, 分类
=未来警告, ) QConfigDynamic(命名元组("Q 配置动态", [激活, 权重])): "" 描述如何通过提供信息动态量化层或网络的一部分 权重设置(观察者类) 它类似于 QConfig,但用于动态量化。 注意,QConfigDynamic 需要包含观察者**类**(如 MinMaxObserver)或一个在调用时返回实例的可调用对象,而不是具体的观察者实例本身。 注意,QConfigDynamic 需要包含观察者**类**(如 MinMaxObserver)或一个在调用时返回实例的可调用对象,而不是具体的观察者实例本身。 量化函数将为每一层实例化观察者多次。 观察者类通常有合理的默认参数,但可以使用 `with_args` 方法(类似于 functools.partial)进行覆盖 方法(行为类似于 functools.partial):: my_qconfig = QConfigDynamic(weight=default_observer.with_args(dtype=torch.qint8)) "文档" __slots__ = () def __new__(, 激活=火把.神经网络.身份, 重量=火把.神经网络.身份): # 捕捉常见错误 如果 isinstance(重量, 神经网络.模块): raise ValueError( "QConfigDynamic 接收到观察者实例,请传递观察者类。" + "如需覆盖构造函数的参数,请使用 MyObserver.with_args(x=1)。" ) 返回 超级().__new__(, 激活, 重量) 默认_qconfig = QConfig(激活=默认观察者, 重量=默认权重观察者) "" 默认 qconfig 配置。 "" 默认调试 qconfig = Q 配置( 重量=默认权重观察者, 激活=默认调试观察者 ) "" 默认的调试 qconfig 配置。 "" 默认每通道 qconfig = Q 配置( 激活=默认观察者, 重量=默认每通道权重观察者 ) "" 每通道权重量化的默认 qconfig 配置。 "" default_dynamic_qconfig = Q 配置( 激活=默认动态量化观察者, 重量=默认权重观察者 ) "" 默认动态 qconfig。 "" float16 动态 qconfig = Q 配置( 激活=占位符观察者.带参数(数据类型=火把.float16, 动态的=), 重量=占位符观察者.带参数(数据类型=火把.float16), ) "" 动态 qconfig,权重量化为`torch.float16`。 "" float16 静态 qconfig = Q 配置( 激活=占位符观察者.带参数(数据类型=火把.float16), 重量=占位符观察者.带参数(数据类型=火把.float16), ) "" 动态 qconfig,激活和权重均量化为`torch.float16`。 "" 每通道动态量化配置 = QConfig( 激活=默认动态量化观察者, 重量=默认通道权重观察者, ) "" 每通道量化权重动态 qconfig。 "" float_qparams_weight_only_qconfig = Q 配置( 激活=默认占位符观察者, 重量=默认浮点零点观察者 ) "" 使用浮点数 zero_point 量化的权重动态 qconfig "" 仅权重浮点 Q 参数_4 位 Q 配置 = Q 配置( 激活=默认占位符观察者, 重量=默认浮点 Q 参数观察者_4 位 ) 默认 QAT 配置 = Q 配置( 激活=默认伪量化, 重量=默认权重伪量化 ) "" QAT 的默认 qconfig。 "" 默认动态 QAT 配置 = Q 配置( 激活=默认动态伪量化, 重量=默认权重伪量化 ) "" 动态 QAT 的默认 qconfig。 "" 默认仅权重权重配置 = QConfig( 激活=火把.神经网络.身份, 重量=默认权重伪量化 ) "" 仅对权重进行量化的默认 qconfig。 "" 默认激活量化配置 = Q 配置( 激活=默认假量化, 重量=火把.神经网络.身份 ) "" 仅对激活进行量化的默认 qconfig。 "" 使用融合观察器和模拟量化模块以优化训练性能的 QAT 配置。 要修改激活/权重观察器,可以修改 fake_quantize.py 中的默认条目。 默认_qat_qconfig_v2 = Q 配置( 激活=默认融合激活假量化, 重量=默认融合权重伪量化 ) "" `default_qat_config`的融合版本,具有性能优势。 "" 默认重用输入 QConfig = QConfig( 激活=默认重用输入观察者, 重量=NoopObserver ) "" 默认 qconfig 配置,用于重用输入张量中的观察者,例如 reshape "" def 获取默认 qconfig(后端="x86", 版本=0): "" 返回指定后端的默认 PTQ qconfig。 参数: * `backend` (str): 表示目标后端的字符串。目前支持 `x86`(默认),`fbgemm`,`qnnpack` 和 `onednn`。 返回: qconfig "文档" 支持的后端 = [fbgemm, x86, qnnpack, onednn] 如果 后端 支持的后端: raise 断言错误( 后端: + 字符串(后端) + f"不支持。后端必须是以下之一"{支持的后端}" ) 如果 版本 == 0: 如果 后端 == "fbgemm": qconfig = Q 配置( 激活=历史图观察者.带参数(范围缩减=), 重量=默认通道权重观察者, ) elif 后端 == qnnpack: # TODO: 使其与 xnnpack 约束兼容 qconfig = Q 配置( 激活=历史图观察者.带参数(范围缩减=错误), 重量=默认权重观察者, ) elif 后端 == onednn: 如果 火把.cpu.支持 VNNI 吗(): 警告.警告( "默认的 oneDNN 后端 qconfig,reduce_range 设置为 false 时可能存在精度问题" "在未支持向量神经网络指令的 CPU 上。" ) qconfig = QConfig( 激活=历史观测器.with_args(范围缩减=错误), 重量=默认每通道权重观察者, ) elif 后端 == x86: qconfig = Q 配置( 激活=历史图观察者.带参数(范围缩减=), 重量=默认通道权重观察者, ) 否则: # 不会到达 qconfig = 默认_qconfig 否则: raise 断言错误( "版本号: " + 字符串(版本) + 在 get_default_qconfig 中不支持。版本号必须是 0 ) 返回 qconfig "" 默认,针对指定后端的对称 PTQ qconfig。以及相同的每个通道的变体。 同样,这里指的是具有零点=0 的符号权重,以及额外的 对称性适用于零点=0 的符号权重,以及额外的 值限制。激活也是使用此签名的 8 位整数 qconfig。 *一旦此更改合并[截至 2022 年 3 月 17 日],如果后端或 qengine 等于 'qnnpack',则可能使用此对称 qconfig 的一些量化算子 xnnpack 库中的算子。 ** 支持使用由`qnnpack`支持的 xnnpack 算子进行非对称 qconfig(由 get_default_qconfig()返回)。 qconfig(由 get_default_qconfig()返回)尚不可用。 * 此 qconfig 使用有符号激活和权重。权重已添加。 限制,例如零点被强制设为 0,使得权重 对称,因此得名。8 位量化值 限制为[-127, +127],排除-128。 xnnpack 有一个量化和缩放值限制,0x1p-32 <= requantization_scale < 256.0 其中,`requantization_scale = (input_scale * kernel_scale) / (output_scale)`。使用此 eps(假设最大值为 256)是为了防止 requantization_scale 低于 xnnpack 的阈值。 * kernel_scale) / (output_scale)`. 使用此 eps(w/ assumed max value of 256)是为了防止 requantization_scale 低于 xnnpack 的阈值。 "" 默认对称 qnnpack_qconfig = Q 配置( 激活=直方图观察者.带参数( 数据类型=火把.qint8, 范围缩减=错误, eps=2**-12 ), 重量=范围观察者_neg_127_to_127, ) 默认_per_channel_symmetric_qnnpack_qconfig = Q 配置( 激活=直方图观察者.带参数( 数据类型=火把.qint8, 范围缩减=错误, eps=2**-12 ), 重量=每通道权重观察者范围-127 到 127, ) 默认嵌入量化 Q 配置 = Q 配置( 激活=Noop 观察者.带参数(数据类型=火把.float32), 重量=默认嵌入伪量化, ) 默认嵌入 QAT 配置 4 位 = Q 配置( 激活=Noop 观察者.带参数(数据类型=火把.float32), 重量=默认嵌入伪量化 4 位, ) 默认量化权重配置 quint8 = QConfig( 激活=直方图观察者, 重量=MinMaxObserver ) def 获取默认 QAT QConfig(后端="x86", 版本=1): "" 返回指定后端的默认 QAT qconfig。 参数: * `backend` (str): 表示目标后端的字符串。目前支持 `x86`(默认),`fbgemm`,`qnnpack` 和 `onednn`。 `版本`: 版本,用于向后兼容。可以是 `None` 或 `1`。 返回: qconfig "文档" 支持的后端 = [fbgemm, x86, qnnpack, onednn] 如果 后端 支持的后端: raise 断言错误( "后端:" + 字符串(后端) + f" 不支持。后端必须是以下之一"{支持的后端}" ) # 直方图观察者在量化感知训练中速度太慢 如果 版本 == 0: 如果 后端 == fbgemm: qconfig = QConfig( 激活=伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=0, 量化最大值=255, 范围缩减=, ), 重量=默认通道权重假量化, ) elif 后端 == qnnpack: qconfig = QConfig( 激活=伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=0, 量化最大值=255, 范围缩减=错误, ), 重量=默认权重伪量化, ) elif 后端 == onednn: qconfig = Q 配置( 激活=模拟量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=0, 量化最大值=255 ), 重量=默认通道权重伪量化, ) elif 后端 == x86: qconfig = QConfig( 激活=伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=0, 量化最大值=255, 范围缩减=, ), 重量=默认每通道权重假量化, ) 否则: qconfig = 默认 QAT 配置 使用融合的观察+假量化模块进行量化加速训练(QAT)。 elif 版本 == 1: 如果 后端 == fbgemm: qconfig = QConfig( 激活=混合移动平均观测器伪量化.带参数( 观测器=移动平均最小最大观测器, 量化最小值=0, 量化最大值=255, 范围缩减=, ), 重量=默认融合每通道权重假量化, ) elif 后端 == qnnpack: # TODO: 使其符合 xnnpack 约束 qconfig = QConfig( 激活=混合移动平均观测伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=0, 量化最大值=255, 范围缩减=错误, ), 重量=默认融合_wt_假量化, ) elif 后端 == onednn: qconfig = Q 配置( 激活=混合移动平均观测伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=0, 量化最大值=255 ), 重量=默认融合每通道权重假量化, ) elif 后端 == x86: qconfig = QConfig( 激活=混合移动平均观测伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=0, 量化最大值=255, 范围缩减=, ), 重量=默认融合通道权重假量化, ) 否则: 配置文件 = 默认_qat_qconfig_v2 否则: raise 断言错误( "版本号:" + 字符串(版本) + "在 get_default_qat_qconfig 中不支持。版本号必须是 0 或 1" ) 返回 qconfig "" qnnpack 的默认对称 QAT qconfig 及其通道权重变体。 "" default_symmetric_qnnpack_qat_qconfig = QConfig( 激活=混合移动平均观测伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=-128, 量化最大值=127, 数据类型=火把.qint8, 范围缩减=错误, eps=2**-12, ), 重量=融合_wt_假量化范围_neg_127_to_127, ) 默认通道对称 qnnpack 量化 qconfig = Q 配置( 激活=混合移动平均观察伪量化.带参数( 观察者=移动平均最小最大观察者, 量化最小值=-128, 量化最大值=127, 数据类型=火把.qint8, 范围缩减=错误, eps=2**-12, ), 重量=混合通道加权伪量化范围-127 到 127, ) 默认_fp32 占位符_qconfig = Q 配置( 激活=占位符观察者.with_args(数据类型=火把.float32), 重量=占位符观察者.with_args(数据类型=火把.float32), ) _默认_quint8 占位符_qconfig = Q 配置( 激活=占位符观察者.带参数(数据类型=火把.quint8), 使用此 qconfig 的运算符没有权重 重量=, ) @deprecated( `torch.ao.quantization.get_default_qconfig_dict` 已弃用,将在未来的版本中删除 请使用 `torch.ao.quantization.get_default_qconfig_mapping` 代替。, 分类=未来警告, ) def get_default_qconfig_dict(后端=x86, 版本=0): 返回 火把.ao.量化.获取默认量化配置映射(后端, 版本).to_dict() @deprecated( "`torch.ao.quantization.get_default_qat_qconfig_dict` 已弃用,并将在未来版本中删除。请使用 `torch.ao.quantization.get_default_qat_qconfig_mapping` 代替。" "在未来版本中。请使用 `torch.ao.quantization.get_default_qat_qconfig_mapping` 代替。", 分类=未来警告, ) def get_default_qat_qconfig_dict(后端=x86, 版本=1): 返回 火把.ao.量化.获取默认 QAT_QCONFIG 映射( 后端, 版本 ).to_dict() def _assert_valid_qconfig(qconfig: 可选[QConfig], 模块: 火把.神经网络.模块) -> : "" 验证此 `qconfig` 是否有效。 "文档" 如果 qconfig : 返回 是否是卷积转置模块 = isinstance( 模块, (火把.神经网络.卷积转置 1d, 火把.神经网络.卷积转置 2d, 火把.神经网络.ConvTranspose3d), ) 如果 是卷积转置模块: 如果 qconfig.权重 : 目前假设任何没有权重的 ConvTranspose 的 qconfig 都是有效的 返回 example 观察者 = qconfig 配置.重量() 每通道 = isinstance( example 观察者, ( 火把.ao.量化.PerChannelMinMax 观察者, 火把.ao.量化.移动平均通道最大最小观察者, ), ) 断言 ( 每通道 ), "通道权重观察者尚未支持 ConvTranspose"{n}d." QConfigAny = 可选[QConfig] QConfigAny.__module__ = "torch.ao.quantization.qconfig" def 添加模块到 qconfig_obs_ctr( qconfig: QConfigAny, 模块: 可选[神经网络.模块] ) -> 任何: r这是一个用于量化准备的帮助函数,用于更新 qconfig,以便存储在 qconfig 中的构造函数将在'module'所在的同一设备上创建观察者。 这是为了在 qconfig 传播到每个模块时使用,以避免潜在的设备对齐问题。 这是为了在 qconfig 传播到每个模块时使用,以避免潜在的设备对齐问题。 这是为了在 qconfig 传播到每个模块时使用,以避免潜在的设备对齐问题。 参数: qconfig:存储在激活和权重中的 QConfig,具有 obs 构造函数 模块:与 qconfig 相关的模块 返回: qconfig:配置为将 obs 构造函数设置在模块相同的设备上构建 "文档" 如果 模块 或者 qconfig 或者 qconfig.字段列表 != (激活, 重量): 返回 qconfig def 根据模块和设备获取工厂参数的键值对(): 断言 isinstance(模块, 火把.神经网络.模块) 设备 = {p.设备 for p 模块.参数()} | { p.设备 for p 模块.缓冲区() } 设备 = 下一(迭代(设备)) 如果 长度(设备) > 0 否则 返回 如果 设备 否则 {"设备": 设备} def 配置构造函数以将观察者放在模块设备上(原始构造函数): 尝试: # 检查构造函数是否可以接受 factory_kwargs 检查 = 原始构造函数.带参数(工厂参数=) 检查() 返回 原始构造函数.带可调用参数( 工厂参数=获取基于模块和设备的工厂参数 ) 除了 属性错误: # qconfig 没有激活或权重 返回 原始构造函数 除了 类型错误: # 该类不接受 factory_kwargs 参数 返回 原始构造函数 激活 = 配置构造函数以将观察者放在模块设备上(q 配置.激活) 权重 = 配置构造函数以将观察者放在模块设备上(qconfig.重量) 返回 QConfig(激活, 重量) _观察者或伪量化构造函数 = 联盟[ _部分包装器, 类型[观察者基类], 类型[模拟量化基类] ] def _观测或全频率控制等于( obs_or_fq1: _观察者或伪量化构造函数, obs_or_fq2: _观察者或伪量化构造函数, ): 如果 isinstance(obs_or_fq1, _部分包装器) 并且 isinstance( obs_or_fq2, _部分包装器 ): 返回 _部分包装器等于(观测或_fq1, 观测或_fq2) 返回 观测或_fq1 == 观测或_fq2 def _部分包装等于(观测或_fq1: _部分包装, 观测或_fq2: 部分包装): "" 返回两个部分包装器是否相等 "文档" functools.partial 没有定义__eq__运算符,所以'=='默认为'is' obs_or_fq1_keywords = 复制.复制(obs_or_fq1.p.关键词) 观测或 FQ2 关键词 = 复制.复制(观测或 FQ2.p.关键词) 关键词等于 = 真实 将观察者构造函数与_obs_or_fq_ctr_equals 进行比较,因为直接比较会失败 如果 观察者 obs_or_fq1_keywords 并且 观察者 观测或 FQ2 关键词: 关键词相等 = 关键词相等 并且 观测或全称控制等于( 观测或全称 1 关键词[观测者], 观测或全称 2 关键词[观察者] ) obs_or_fq1_关键词.流行(观察者) obs_or_fq2_关键词.流行(观察者) 关键词相等 = 关键词等于 并且 观测或 FQ1 关键词 == 观测或 FQ2 关键词 返回 ( 观测或_fq1.p.函数 == 观测或_fq2.p.函数 并且 观测或_fq1.p.args == 观测或_fq2.p.args 并且 关键词相等 ) def qconfig_equals(q1: QConfigAny, q2: QConfigAny): "" 如果 `q1` 等于 `q2`,则返回 `True`,否则返回 `False`。 "文档" 如果 q1 或者 q2 : 返回 q1 == q2 否则: 断言 q1 并且 q2 尝试: # Qconfig 权重和激活可以是部分包装, # 或者观察者类。需要特殊处理(上面所述)。 比较部分包装 激活相同 = _观察或全频段计数器相等(q1.激活, q2.激活) 重量相同 = 观测或全频段计数器等于(q1.重量, q2.重量) 返回 激活相同 并且 重量相同 除了 属性错误: 返回 问题 1 == 问题 2 def 激活函数是无记忆的(qconfig: QConfig): "" 返回是否在给定的 QConfig 中定义的激活观察者是记忆的。 这意味着平均常数为 1 的移动平均观察者。 "文档" def _is_memoryless(观察者): 返回 ( 有属性(观察者, 平均常数) 并且 观察者.平均常数 == 1 ) 动作 = 配置.激活() 如果 isinstance(动作, 模拟量化基类) 并且 有属性(动作, 激活后处理): 返回 _无记忆(动作.激活后处理) 否则: 返回 _无记忆(动作) def _重用输入 q 配置(qconfig: 可选[QConfig)] 返回 ( qconfig 并且 isinstance(qconfig.activation(), ReuseInputObserver) 并且 isinstance(qconfig.重量(), NoopObserver) )

© 版权所有 PyTorch 贡献者。

使用 Sphinx 构建,并使用 Read the Docs 提供的主题。

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

深入了解初学者和高级开发者的教程

查看教程

资源

查找开发资源,获取您的疑问解答

查看资源