torch.jit._freeze 的源代码
# mypy: 允许未类型化定义
冻结。
不建议直接导入;请使用`torch.jit`中公开的功能。
请使用`torch.jit`中公开的功能。
""
from 打字
导入
可选
导入
火炬
from torch.jit._script 导入
递归脚本模块,
脚本模块
[文档]def
冻结(
模块,
保留属性:
可选[
列表[
字符串]] =
无,
优化数值:
布尔值 =
真实
):
r冻结脚本模块、内联子模块和属性为常量。
冻结 :class:`ScriptModule` 将会克隆它并尝试内联克隆后的
模块的子模块、参数和属性作为常量在 TorchScript IR 图中。
默认情况下,`forward` 将被保留,以及指定的属性和方法
保留属性。另外,任何在保留属性中修改的属性
方法将被保留。
目前 Freezing 仅接受处于 eval 模式的 ScriptModules。
Freezing 应用通用的优化,这将加快您的模型运行速度,不受机器影响。
要进一步使用服务器特定设置进行优化,请在 freezing 后运行`optimize_for_inference`。
。
参数:
mod (:class:`ScriptModule`): 要冻结的模块
preserved_attrs (Optional[List[str]]): 除了前向方法外,还要保留的属性列表。
在保留方法中修改的属性也将被保留。
optimize_numerics (bool): 如果为 ``True``,将运行一组优化过程,这些过程并不严格
保留数字。优化详情请参阅 `torch.jit.run_frozen_optimizations`。
返回:
冻结 :class:`ScriptModule`。
示例(冻结一个简单的模块带有参数):
.. testcode::
导入 torch
class MyModule(torch.nn.Module):
def __init__(self, N, M):
super().__init__()
self.weight = torch.nn.Parameter(torch.rand(N, M))
self.linear = torch.nn.Linear(N, M)
def forward(self, input):
output = self.weight.mm(input)
output = self.linear(output)
返回输出
scripted_module = torch.jit.script(MyModule(2, 3).eval())
frozen_module = torch.jit.freeze(scripted_module)
# 参数已被移除并内联到图中作为常量
assert len(list(frozen_module.named_parameters())) == 0
# 查看编译后的图作为 Python 代码
print(frozen_module.code)
示例(冻结具有保留属性的模块)
.. testcode::
导入 torch
class MyModule2(torch.nn.Module):
def __init__(self) -> None:
super().__init__()
self.modified_tensor = torch.tensor(10.)
self.version = 1
def forward(self, input):
self.modified_tensor += 1
返回输入加上 self.modified_tensor
将 MyModule2().eval()脚本化
冻结脚本化模块,保留属性["version"]
我们已手动保留`version`,因此它仍然存在于冻结模块中并可修改
assert frozen_module.version == 1
frozen_module.version = 2
# `modified_tensor` 在前向传播中被检测为发生了变化,因此冻结以保留模型语义
# 以保留模型语义
assert frozen_module(torch.tensor(1)) == torch.tensor(12)
现在我们已经运行过一次,下一次的结果将增加一
assert frozen_module(torch.tensor(1)) == torch.tensor(13)
注意:
支持冻结子模块属性:
frozen_module = torch.jit.freeze(scripted_module, preserved_attrs=["submodule.version"])
注意:
如果您不确定为什么某个属性没有被内联为常量,您可以在 frozen_module.forward.graph 上运行`dump_alias_db`来查看是否检测到该属性被修改。
`dump_alias_db`在 frozen_module.forward.graph 上运行,以查看是否检测到该属性正在被修改。
属性正在被修改。
注意:
因为冻结使权重成为常数并移除了模块层次结构,`to`和其他 nn.Module 方法无法操作设备或 dtype。
作为解决方案,您可以在`torch.jit.load`中指定`map_location`来重新映射设备。
然而,模型中可能已经包含了特定设备的逻辑。
设备特定的逻辑可能已经被嵌入到模型中。
"文档"
如果
不 isinstance(
模块,
脚本模块):
提升
运行时错误(
"Freezing 需要以 ScriptModule 作为输入。"
"请使用 torch.jit.script 或 torch.jit.trace 将您的'nn.Module'脚本化。"
)
如果
模块.
训练:
提升
运行时错误(
"目前 Freezing 仅对 eval 模式的模块进行了实现。"
"请在冻结之前调用您的模块的.eval()方法。"
)
保留属性 =
保留属性
如果
保留属性 is
不
无
否则
输入文本为空,请提供需要翻译的文本
out = 递归脚本模块(
火炬._C.
冻结模块(
模块._c,
保留属性))
递归脚本模块.
_完成脚本模块(
输出)
保留方法 = [x
为 x
在
保留属性
如果
模块._c._has_method(x)]
run_frozen_optimizations(输出, optimize_numerics, preserved_methods)
返回
输出
def 运行冻结优化(
模块,
优化数值:
布尔值 =
是,
保留的方法:
可选[
列表[
字符串]] =
无
):
r""
运行一系列优化,寻找在冻结图中出现的模式。
当前优化集包括:
- Dropout 移除
- 预转置线性层
- 连接具有相同输入张量的线性层
- 卷积 -> 批归一化折叠
- 卷积 -> 加/减折叠
- 卷积 -> 乘/除折叠
参数:
mod (:class:`ScriptModule`): 一个用于优化的冻结模块
优化数值(布尔值):如果为 ``True``,将运行一组优化过程,这些过程并不严格
保留数值。这些优化保留了`torch.testing.assert_close`的默认 rtol 和 atol
当应用于单个转换时,然而在一个应用了许多转换的模块中
rtol 或 atol 可能不再在默认的 `assert_close` 容忍度范围内。Conv -> Batchnorm 折叠
卷积加/减和卷积转换为乘/除折叠都可能改变数值。
返回:
无
注意:
在极少数情况下,这可能会导致执行速度变慢。
示例(冻结带有卷积->批归一化的模块)
.. 代码块 :: python
导入 torch
输入通道数,输出通道数 = 3, 32
conv = torch.nn.Conv2d(
in_channels, out_channels, kernel_size=3, stride=2, bias=True
)
bn = torch.nn.BatchNorm2d(out_channels, eps=0.001)
mod = torch.nn.Sequential(conv, bn)
# 将 optimize 设置为 False,默认情况下冻结运行运行冻结优化
frozen_mod = torch.jit.freeze(torch.jit.script(mod.eval()), optimize=False)
# 检查冻结的模块
assert "batch_norm" in str(frozen_mod.graph)
torch.jit.run_frozen_optimizations(frozen_mod)
assert "batch_norm" not in str(frozen_mod.graph)
"文档"
如果
模块._c._has_method(
前进):
火炬._C._jit_pass_optimize_frozen_graph(
模块.graph,
优化数值)
如果
保留方法 is
无:
保留方法 =
输入文本为空,请提供需要翻译的文本
为
方法
在
保留方法:
火炬._C._jit_pass_optimize_frozen_graph(
模块.__getattr__(
方法).graph,
优化数值
)
[文档]def
优化推理(
模块:
脚本模块,
其他方法:
可选[
列表[
字符串]] =
无
) 翻译
脚本模块:
""
执行一系列优化步骤以优化模型用于推理。
如果模型尚未冻结,将自动调用 `torch.jit.freeze` 进行优化。
除了通用的优化应该加快您的模型运行速度之外,
准备推理阶段还会嵌入针对构建的具体设置。
无论环境如何,准备推理阶段也会嵌入针对构建的具体设置。
例如,存在 CUDNN 或 MKLDNN,并且未来可能会进行转换
这在一台机器上可以加快速度,但在另一台机器上会减慢速度。因此,
在调用`optimize_for_inference`之后没有实现序列化
这并不保证。
这仍然处于原型阶段,可能会降低您的模型性能。
目前已针对的目标主要使用案例是 CPU 上的视觉模型。
以及在某种程度上是 GPU。
示例(优化模块:卷积->批归一化)::
导入 torch
in_channels, out_channels = 3, 32
conv = torch.nn.Conv2d(
in_channels, out_channels, kernel_size=3, stride=2, bias=True
)
bn = torch.nn.BatchNorm2d(out_channels, eps=0.001)
mod = torch.nn.Sequential(conv, bn)
frozen_mod = torch.jit.optimize_for_inference(torch.jit.script(mod.eval()))
assert "batch_norm" not in str(frozen_mod.graph)
# 如果使用 MKLDNN 构建,卷积将使用 MKLDNN 权重运行
断言 "MKLDNN" 在 frozen_mod.graph 中
"文档"
如果
不 isinstance(
模块,
脚本模块):
提升
运行时错误(
"optimize_for_inference 期望输入一个 ScriptModule。"
"请使用 torch.jit.script 或 torch.jit.trace 将您的 'nn.Module' 脚本化。"
)
如果
其他方法 is
无:
其他方法 =
输入文本为空,请提供需要翻译的文本
如果
有属性(
模块,
"训练"):
修饰 =
冻结(
模块.
评估(),
保留属性=
其他方法)
火炬._C._jit_pass_optimize_for_inference(
模块._c,
其他方法)
返回
模块