torch.ao.quantization.pt2e.export_utils 的源代码
# mypy: 允许未类型化定义
导入
类型
导入
火炬
导入 torch.nn.functional
作为 F
从 torch.ao.quantization.utils
导入 _assert_and_get_unique_device
__all__ = [
模型已导出,
]
_已导出训练属性 =
_已导出训练
类
包装模块(torch.
神经网络.
模块):
"""将可调用对象包装在 :class:`torch.nn.Module` 中的类。如果您尝试导出可调用对象,请使用此类。"""
如果您正在尝试导出可调用对象。
"""
def __init__(self, fn):
super().__init__()
self.fn = fn
定义
前进(
自己, *
参数, **kwargs):
简单的前向调用,仅调用在:meth:`WrapperModule.__init__`中提供的`fn`。
返回 self.fn(*
参数, **
关键字参数)
[文档]def 模型是否导出(m: torch.nn.Module) -> bool:
""
返回 `torch.nn.Module` 是否已导出,如果是则返回 True,否则返回 False
(例如,如果模型被 FX 符号化追踪或根本未追踪)。
""
return isinstance(m, torch.fx.GraphModule) and any(
"val" in n.meta for n in m.graph.nodes
)
def 替换丢弃(m:
PyTorch.fx.
图模块,
训练到评估:
布尔):
"""
在训练和评估模式之间切换模型的 dropout 模式。
训练模式和评估模式下的 Dropout 行为不同。对于导出的模型,
然而,调用`model.train()`或`model.eval()`并不会自动切换
两种模式下的 dropout 行为,因此在这里我们需要手动重写 aten
dropout 模式以实现相同的效果。
请参阅 https://github.com/pytorch/pytorch/issues/103681。
"""
避免循环依赖
导入 .utils
导入 _get_aten_graph_module_for_pattern
# 需要确保子图匹配是自包含的
m.图.
删除死代码()
m.重新编译()
对于
内置
在 [
假,
真
]
def dropout_train(x):
return F.丢弃(x, p=0.5,
训练=
是的,
就地=
内置)
定义
dropout 评估(x):
返回 F.
丢弃(x, p=0.5,
训练=
错误,
就地=
内置)
示例输入 = (
火炬.
随机正态分布(1),)
如果
训练到评估:
匹配模式 =
为模式获取_aten_graph_module(
包装模块(dropout_train),
示例输入,
)
替换模式 =
获取用于模式的 Aten 图模块(
包装模块(
dropout 评估),
示例输入,
)
else:
匹配模式 = _get_aten_graph_module_for_pattern(
_WrapperModule(dropout 评估),
示例输入,
)
替换模式 =
_根据模式获取 aten 图模块(
包装模块(dropout_train),
示例输入,
)
来自 torch.fx.subgraph_rewriter
导入
用过滤器替换模式
用过滤器替换模式(
m,
匹配模式,
替换模式,
匹配过滤器=
[]
忽略字面意思=
真的,
)
m.重新编译()
定义
替换批量归一化(m:
PyTorch.fx.
图模块,
训练到评估:
布尔):
"""
在模型中在训练和评估模式之间切换批量归一化模式。
批归一化在训练模式和评估模式下的行为不同。对于导出的模型,
然而,调用 `model.train()` 或 `model.eval()` 并不会自动切换
批归一化的行为,因此在这里我们需要手动重写 aten
批归一化模式以实现相同的效果。
"""
# TODO(莱斯利): 此函数仍然不支持自定义动量和 eps 值。
# 在未来更新中启用此功能。
# 避免循环依赖
从 .utils
导入 _get_aten_graph_module_for_pattern
需要确保子图匹配是自包含的
m.图.
消除死代码()
m.重新编译()
def bn_train(
x: torch.Tensor,
bn_weight: torch.Tensor,
bn_bias: 火炬.
张量,
bn 运行均值:
火炬.
张量,
bn 运行变量:
PyTorch.
张量,
):
返回 F.
批标准化(
x, 批标准化运行均值,
批标准化运行方差, bn_weight, bn_bias,
训练=
是的
)
def bn 评估(
x: torch.张量,
bn_weight: torch.Tensor,
bn_bias: 火炬.
张量,
bn 运行均值:
火炬.
张量,
bn 运行变量:
PyTorch.
张量,
):
返回 F.
批标准化(
x, 批标准化运行均值,
批标准化运行方差,
bn 权重,
bn 偏置,
训练=False
)
示例输入 = (
torch.randn(1, 1, 3, 3), # x
火炬.
随机正态分布(1), # bn_weight
火炬.randn(1), # bn_bias
torch.randn(1), # bn_running_mean
火炬.randn(1), # bn_running_var
)
设备 =
_断言并获取唯一设备(m)
是否为 CUDA =
设备
是
不是
无
并且
设备.
类型 == "cuda"
bn_train_aten = 获取用于模式的 Aten 图模块(
包装模块(
bn 训练),
示例输入,
is_cuda,
)
bn_eval_aten = _get_aten_graph_module_for_pattern(
_WrapperModule(bn 评估),
示例输入,
is_cuda,
)
如果
训练到评估:
匹配模式 = bn_train_aten
替换模式 = bn_eval_aten
else:
match_pattern = bn_eval_aten
替换模式 = bn_train_aten
来自 torch.fx.subgraph_rewriter
导入
用过滤器替换模式
用过滤器替换模式(
m,
匹配模式,
替换模式,
匹配过滤器=
[]
忽略字面量=
真实,
)
m.重新编译()
# TODO: 在此命名空间下公开这些?
定义
将导出模型移动到评估(
模型:
PyTorch.fx.
Graph 模块):
"""
将导出的 Graph 模块移动到评估模式。
这与 model.eval()等价,但仅适用于某些特殊操作,如 dropout、batchnorm。
QAT 用户应在模型上进行推理之前调用此操作。
此调用是幂等的;如果模型已经处于评估模式,则不会发生任何操作。
"""
is_training = getattr(模型,
_导出训练属性, True)
如果
否则
是否训练中:
返回
模型
设置属性(
模型,
_导出训练属性,
错误)
_替换 dropout(
模型,
训练到评估=
真实)
_替换批量归一化(
模型,
训练到评估=
真实)
返回
模型
定义
将导出模型移动到训练(
模型:
PyTorch.fx.
Graph 模块):
"""
将导出的 Graph 模块移动到训练模式。
这与 model.train()等价,但仅适用于某些特殊的操作,如 dropout、batchnorm。
QAT 用户应在模型训练之前调用此操作。
此调用是幂等的;如果模型已经在训练模式,则不会发生任何操作。
"""
is_training = getattr(model, _导出训练属性, False)
如果
训练中:
返回
模型
setattr(模型,
_导出训练属性, True)
替换丢弃(
模型,
训练到评估=
否)
替换批量归一化(
模型,
训练到评估=False)
返回
模型
定义
_允许导出模型训练评估(
模型:
PyTorch.fx.
图模块):
```python
# 假设输入文本为:
input_text = """Immersive Translate"""
# 翻译函数(此处仅为示例,实际翻译功能需要调用真实的翻译 API)
def translate_to_simplified_chinese(text):
# 这里应该调用真实的翻译 API 进行翻译
# 由于示例中不使用真实的 API,以下为模拟翻译结果
return text # 假设翻译结果与原文相同
# 输出翻译结果
translated_text = translate_to_simplified_chinese(input_text)
print(translated_text)
```
输出:
```
Immersive Translate
```
允许用户在导出的模型上调用 `model.train()` 和 `model.eval()`
但是两种模式之间行为变化的效果仅限于特殊
仅限操作,目前为 dropout 和 batchnorm。
注意:这并不达到 `model.train()` 和 `model.eval()` 相同的效果
在急切模型中执行,但只提供近似值。特别是用户代码
分支在`training`标志上通常不会正确工作
已专门在导出时设置。此外,还有除 dropout 和 batchnorm 之外的其他操作
具有不同训练/评估行为的也将无法正确转换。
"""
定义
_训练(
我,
模式:
布尔 =
真):
如果
模式:
_将导出的模型移动到训练(
自身)
否则:
_将导出模型移动到评估(self)
def 评估(
自身):
将导出的模型移动到评估(
自身)
模型.
训练 =
类型.
方法类型(
训练,
模型) # type: ignore[method-assign]
模型.
评估 =
类型.
方法类型(
_评估,
模型) # type: ignore[method-assign]
返回
模型