torch.ao.quantization.fuse_modules 源代码
# mypy: 允许未类型化定义
导入
复制
from 打字
导入
可选
导入 torch.nn
是
神经网络
# 为向后兼容
from torch.ao.quantization.fuser_method_mappings 导入 (
# 无需检查:F401
融合卷积归一化,
融合卷积批量归一化 ReLU,
获取用户方法,
)
from torch.nn.utils.parametrize 导入 type_before_parametrizations
全部 = [
熔合已知模块,
"融合模块",
"融合模块_qat",
]
getattr 的一般化
定义
获取模块(
模型,
子模块键):
标记 =
子模块键.
分割(
“。”)
当前模块 =
模型
for s 在
令牌:
当前模块 = getattr(
当前模块, s)
返回
当前模块
setattr 的一般化
定义 _set_module(
模型,
子模块键,
模块):
令牌 =
子模块键.
分割(
“。”)
子令牌 =
令牌
[-1]
当前模块 =
模型
for s 在
子词:
当前模块 = getattr(
当前模块, s)
setattr(当前模块,
令牌[-1
],
模块)
定义
合并已知模块(
模块列表,
是否是 qat,
额外融合方法映射=
无):
r返回已知融合模块的列表。
返回融合指定操作的模块列表。
在输入模块列表中。
仅融合以下模块序列:
conv, bn
conv, bn, relu
卷积,ReLU
线性,归一化
线性,ReLU
对于这些序列,输出模块列表中的第一个元素执行
混合操作。其余元素设置为 nn.Identity()
"文档"
类型 =
元组(
参数化前的类型(m) for m
在
模块列表)
融合方法 =
获取_fuser 方法(
类型,
额外_fuser 方法映射)
如果
fuser 方法
是
无:
raise 不支持的操作异常(f
无法融合模块:{
类型}")
新模块:
列表[
可选[
神经网络.
模块]] = [
无] *
长度(
模块列表)
fused = 融合方法(
是否启用 QAT, *mod_list)
# 注意:在接下来的两个循环中未处理的 forward hooks 将在融合后丢失
# 将基础模块的预 forward hooks 移动到结果融合模块
for pre_hook_fn 在
模块列表[0].
_前向预处理钩子.
值():
融合.
注册前向钩子(
预钩子函数)
模块列表[0].
_前向预处理钩子.
清晰()
将最后一个模块的后置钩子移动到结果融合模块中
for 钩子函数
在
模块列表[-1].
_前向钩子.
值():
融合.
注册前向钩子(
钩子函数)
模块列表[-1].
_前向钩子.
清晰()
新模块[0] = fused
for i 在
范围(1,
长度(
模块列表)):
身份 =
神经网络.
身份()
身份.
训练 =
模块列表[0].
训练
新模块[i] =
身份
返回
新模块
定义
_融合模块助手(
模型,
要融合的模块,
是否是 QAT,
火焰函数=
熔合已知模块,
熔合自定义配置字典=
无,
):
如果
熔合自定义配置字典
是
无:
熔合自定义配置字典 = {}
额外熔合方法映射 =
熔合自定义配置字典.
获取(
"附加融合方法映射", {}
)
模块列表 = [
_获取模块(
模型,
项目) for
项目
在
模块融合列表]
模块列表融合
新模块列表 =
融合函数(
模块列表,
是_qat,
附加的 fuser 方法映射)
用融合的模块列表替换原始模块列表
for i, 项目
在
列举(
要融合的模块):
设置模块(
模型,
项目,
新模块列表[i])
定义
合并模块(
模型,
要合并的模块,
是否是 QAT,
内置=
错误,
火焰函数=
熔合已知模块,
熔合自定义配置字典=
无,
):
如果
不
内置:
模型 =
复制.
深拷贝(
模型)
如果
所有(isinstance(
模块元素,
字符串) for
模块元素
在
要融合的模块):
# 处理 modules_to_fuse 为列表的情况
混合模块助手(
模型,
模块融合,
是否启用 QAT,
融合器函数, fuse_custom_config_dict
)
否则:
处理 modules_to_fuse 为列表的列表的情况
for 模块列表
在
要融合的模块:
_模块辅助函数(
模型,
模块列表,
是否启用 QAT,
融合器函数,
熔合自定义配置字典
)
返回
模型
[文档]
定义
模块融合(
模型,
要融合的模块,
内置=
错误,
将模块列表融合成一个单一模块。=
已知的融合模块。,
自定义配置字典的融合。=
无,
):
r将一系列模块融合成一个模块。
仅融合以下模块序列:
conv, bn
conv, bn, relu
conv, relu
线性,ReLU
批标准化,ReLU
所有其他序列保持不变。
对于这些序列,替换列表中的第一个项目。
使用融合模块,替换其余模块
具有身份。
参数:
模型:包含要融合的模块的模型
modules_to_fuse:要融合的模块名称的列表。也可以是一个列表
如果只有一个模块列表要融合,则返回字符串。
inplace: 布尔值,指定融合是否在模型中就地发生,默认为
返回一个新的模型
fuser_func: 函数,接收一个模块列表作为输入,输出一个融合后的模块列表
长度相同。例如,
fuser_func([convModule, BNModule]) 返回列表 [ConvBNModule, nn.Identity()]
默认为 torch.ao.quantization.fuse_known_modules
`fuse_custom_config_dict`:融合的定制配置
.. 代码块 :: python
# 熔合自定义配置字典示例
fuse_custom_config_dict = {
# 其他 fuser_method 映射
"additional_fuser_method_mapping": {
(torch.nn.Conv2d, torch.nn.BatchNorm2d): 熔合卷积和归一化层
},
}
返回:
具有熔合模块的模型。如果 inplace=True,则创建一个新的副本。
示例:
>>> # xdoctest: +SKIP
>>> m = M().eval()
>>> # m 是包含以下子模块的模块
>>> modules_to_fuse = [ ['conv1', 'bn1', 'relu1'], ['submodule.conv', 'submodule.relu']]
>>> fused_m = torch.ao.quantization.fuse_modules(m, modules_to_fuse)
>>> output = fused_m(input)
>>> m = M().eval()
>>> # 交替提供要融合的单个模块列表
>>> modules_to_fuse = ['conv1', 'bn1', 'relu1']
>>> fused_m = torch.ao.quantization.fuse_modules(m, modules_to_fuse)
>>> output = fused_m(input)
"文档"
返回
合并模块(
模型,
要合并的模块,
是否启用 QAT=
错误,
内置=
内置,
合并函数=fuser_func,
熔断自定义配置字典=
熔断自定义配置字典,
)
定义
熔断模块 qat(
模型,
模块融合,
内置=
错误,
融合函数=
融合已知模块,
融合自定义配置字典=
无,
):
`fuse_modules` 的 QAT 版本。
返回 _fuse_modules(
模型,
要融合的模块,
是否是 QAT=
是,
内置=
内置,
fuser_func=fuser_func,
熔断自定义配置字典=
熔断自定义配置字典,
)