• 文档 >
  • 模块代码 >
  • torch >
  • torch.onnx >
  • torch.onnx._internal._exporter_legacy
快捷键

torch.onnx._internal._exporter_legacy 的源代码

# mypy: 允许未类型化定义
来自 未来 导入 注释


__all__ = [
    "诊断选项",
    "导出选项",
    ONNX 运行时选项,
    无效导出选项错误,
    ONNX 注册表,
    不满足依赖错误,
    dynamo 导出,
    启用模拟模式,
]


导入 abc
导入 contextlib
导入 dataclasses
导入 记录日志
导入 警告
来自 集合 导入 defaultdict
来自 打字 导入 任意, 可调用, 类型检查, 类型变量
来自 typing_extensions 导入 已弃用

导入 火炬
导入 torch._ops
导入 torch.utils._pytree 作为 pytree
来自 torch.onnx 导入 错误
来自 torch.onnx._internal 导入 离线适配器
来自 torch.onnx._internal._lazy_import 导入 onnxscript_apis, onnxscript_ir 作为 ir
来自 torch.onnx._内部诊断 导入 基础设施
来自 torch.onnx._internal.exporter 导入 _constants, _onnx 程序
来自 torch.onnx._internal.fx 导入 (
    分解表,
    patcher 作为 修补器,
    注册,
)


# 我们只能在类型检查的上下文中从这个模块导入 onnx,以确保
# 'import torch.onnx' 继续工作,即使没有安装 'onnx'。我们完全
在 dynamo_export(通过_assert_dependencies 方式)内部导入 onnx
如果 类型检查:
    导入 输入/输出
    来自 collections.abc 导入 映射, 序列

    导入 onnxruntime
    导入 onnxscript

    来自 torch._subclasses 导入 fake_tensor
    来自 torch.onnx._internal.fx 导入 诊断

_PYTORCH_GITHUB_ISSUES_URL = "https://github.com/pytorch/pytorch/issues"
"PyTorch GitHub 问题页面网址。"

_DEFAULT_FAILED_EXPORT_SARIF_LOG_PATH = "report_dynamo_export.sarif"
"如果导出失败,则写入 SARIF 日志的默认路径。"


日志 = 记录日志.获取日志记录器(__name__)


诊断选项 = 基础设施.诊断选项


@dataclasses.数据类
 ONNX 伪造上下文:
    一个用于存储使用 FakeTensor 导出模型上下文的 dataclass。

此数据类存储用于转换的 FakeTensorMode 实例
将真实张量和模型参数转换为假张量。此 :attr:`ONNXFakeContext.fake_mode` 是
在追踪一个 :class:`torch.nn.Module` 到 FX :class:`GraphModule` 时内部重用。
"源代码"

    模拟模式: 伪造张量.模拟 Tensor 模式
    用于跟踪模型使用伪造张量和参数的模拟张量模式。

    state_dict_paths: 元组[字符串 | 输入/输出.BytesIO | 字典[字符串, 任意]] |  = 
    包含模型 :meth:`state_dict` 的文件路径列表。


@deprecated(
    torch.onnx.dynamo_export 自 2.7.0 版本以来已弃用。请使用 torch.onnx.export(..., dynamo=True) 代替。,
)
 Onnx 注册表:
    ONNX 函数注册表。

已弃用
请使用 ``torch.onnx.export(..., dynamo=True)`` 代替。

该注册表维护了合格名称到固定 opset 版本下符号函数的映射。
它支持注册自定义 onnx-script 函数,并为调度器提供调用适当函数的功能。
调度器用于调度调用到相应的函数。

"源代码"

    def 初始化(self) -> :
        初始化注册表

        # 注意:_registry 是将 OpName 映射到 ONNXFunctions 列表的注册表。直接修改此变量是不重要的
        # 应当通过公共方法:register_custom_op、get_ops 和 is_registered_op 来访问它。
        # 公共方法包括:注册自定义操作、获取操作列表和检查操作是否已注册。
        self._注册表: 字典[注册.操作名称, 列表[注册.ONNX 函数]] = (
            defaultdict(列表)
        )

        self._opset 版本 = _constants.TORCHLIB_OPSET
        warnings.警告(
            ftorch.onnx.dynamo_export 仅实现 opset 版本{self._opset_version}目前。如果您需要使用一个“
            不同 opset 版本,请使用 register_custom_op 进行注册。
        )

        self.从 torchlib 初始化注册表()

    @property
    def opset 版本(self) -> int:
        导出器应针对的 ONNX 操作集版本。

        返回 self._opset_version

    def 从 torchlib 初始化注册表(self) -> :
        向注册表填充来自 torchlib 的 ATen 函数。

参数:
torchlib_registry:用于填充注册表的 torchlib 注册表。
"源代码"
         元数据  onnxscript_apis.get_torchlib_ops():
            内部名称实例 = 注册.操作名称.来自限定名称(
                元数据.qualified_name
            )
            符号函数 = 注册.ONNX 函数(
                onnx 函数=元数据.函数,  # type: ignore[arg-type]
                全名操作=实例内部名称.合法名称(),
                自定义=错误,
                是复杂的=元数据.是复杂的,
            )
            self.注册(实例内部名称, 符号函数)

    def 注册(
        self,
        内部限定名: 注册.操作名称,
        符号函数: 注册.ONNX 函数,
    ) -> :
        """将 ONNX 函数注册到算子中。

参数:
internal_qualified_name: 要注册的算子的限定名称:OpName。
symbolic_function: 要注册的 ONNX 函数。
"源代码"
        self._注册表[内部限定名称].追加(符号函数)

[文档] def 注册操作( self, 函数: onnxscript.OnnxFunction | onnxscript.TracedOnnxFunction, 命名空间: str, 操作名称: str, 覆载: str | None = None, is_complex: 布尔 = False, ) -> None: """注册自定义操作:torch.ops.... Args: 函数:用于注册的 onnx-sctip 函数。 命名空间:要注册的操作员的命名空间。 op_name:要注册的操作员名称。 重载:注册运算符的重载。如果它是默认重载, 放任它为空。 is_complex:判断该函数是否处理复数值输入的函数。 抛出: ValueError:如果名称不是 'namespace::op' 的形式。 """ internal_name_instance = registration.OpName.from_name_parts( namespace=namespace, op_name=op_name, overload=overload ) symbolic_function = registration.ONNXFunction( onnx_function=function, op_full_name=internal_name_instance.qualified_name(), is_custom=True, is_complex=是复杂的, ) self._register(内部名称实例, 符号函数)
[文档] def 获取操作函数( self, 命名空间: str, 操作名称: str, 载荷: str | None = None ) -> list[registration.ONNXFunction] | None: """返回给定操作:torch.ops... 的 ONNXFunction 列表。 列表按注册时间排序。自定义操作应该为 列表的后半部分。 参数: 命名空间:获取操作符的命名空间。 op_name:获取的操作符的名称。 运算符获取的重载。如果使用默认重载, 则将其留空。 返回值: 与给定名称对应的 ONNX 函数列表,或如果没有找到则返回 None。 该名称不在注册表中。 """ internal_name_instance = registration.OpName.from_name_parts( namespace=namespace, op_name=op_name, overload=overload ) return self._registry.get(internal_name_instance)
[文档] def is_registered_op( self, 命名空间: str, 操作名称: str, 超载: str | None = None -> bool: 返回是否已注册给定操作:torch.ops.... Args: namespace: 要检查的操作的命名空间。 操作符名称:要检查的操作符名称。 要检查的操作符的重载。如果是默认重载,请留空。 留空为 None。 返回值: 真的如果给定的操作已注册,否则为假。 """ functions = self.get_op_functions( namespace=namespace, op_name=op_name, overload=overload ) 返回函数不为空
def _所有已注册的操作
(self) -> 集合[字符串]: 返回所有已注册函数名的集合。 返回 { op_name_class.合法名称() op_name_class self._注册表.() } @deprecated( "torch.onnx.dynamo_export 自 2.7.0 起已弃用。请使用 torch.onnx.export(..., dynamo=True)代替。", 分类=, ) 导出选项: TorchDynamo ONNX 导出器的选项,用于影响导出过程。 已弃用 请使用 ``torch.onnx.export(..., dynamo=True)`` 代替。 属性: dynamic_shapes: 输入/输出张量的形状信息提示。 当为 ``None`` 时,导出器将确定最兼容的设置。 当为 ``True`` 时,所有输入形状都被视为动态。 当为 ``False`` 时,所有输入形状都被视为静态。 诊断选项:导出器的诊断选项。 伪造上下文:用于符号跟踪的伪造上下文。 onnx_registry:用于将 ATen 运算符注册到 ONNX 函数的 ONNX 注册表。 "源代码" 动态形状: 布尔类型 | = 输入/输出张量的形状信息提示。 - ``None``:导出器确定最兼容的设置。 - ``True``:所有输入形状都被视为动态。 - ``False``:所有输入形状都被视为静态。 "源代码" 诊断选项: DiagnosticOptions 导出器的诊断选项。 模拟上下文: ONNX 假上下文 | = 用于符号跟踪的假上下文。 onnx 注册表: OnnxRegistry | = "用于将 ATen 运算符注册到 ONNX 函数的 ONNX 注册表。" def 初始化( self, *, 动态形状: 布尔类型 | = , 伪造的上下文: ONNX 伪造上下文 | = , onnx 注册表: OnnxRegistry | = , 诊断选项: 诊断选项 | = , ): self.dynamic_shapes = dynamic_shapes self.模拟上下文 = 模拟上下文 self.ONNX 注册表 = ONNX 注册表 self.诊断选项 = 诊断选项 诊断选项() @deprecated( "自 2.7.0 版本起,torch.onnx.dynamo_export 已被弃用。请使用 torch.onnx.export(..., dynamo=True)代替。", 分类=, ) 已解决的导出选项(导出选项): """整合具有默认值的 :class:`ExportOptions`。 所有未指定的`:class:`ExportOptions`选项都分配了默认值。 这是一个内部类,其 API 可能会在任何时候未经通知而更改。 ```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) ``` 公共属性必须在下方重新定义,无需从“ExportOptions”中包含“Optional[]” 动态形状: 布尔类型 诊断选项: DiagnosticOptions 模拟上下文: ONNX 模拟上下文 onnx 注册表: Onnx 注册表 # 仅私有属性 分解表: 字典[火炬.操作符.操作重载, 可调用] “一个将算子映射到其分解函数的字典。” onnxfunction_dispatcher: ( 火炬.onnx.内部.fx.onnxfunction_dispatcher.OnnxFunctionDispatcher ) 用于将 ATen 运算符调度到 ONNX 函数的 ONNX 调度器。 fx_tracer: FXGraphExtractor 用于从模型中提取 FX 图的 FXGraphExtractor 实例。 diagnostic_context: 诊断.DiagnosticContext 导出诊断上下文。负责记录诊断信息。 记录诊断信息,并生成 SARIF 日志。 def 初始化( self, 选项: 导出选项 | 已解决导出选项, 模型: 火炬.nn.模块 | 可调用 | = , 忽略名称定义 ): 来自 torch.onnx._internal.fx 导入 ( 防止循环依赖 诊断, dynamo_graph_extractor, ) 如果 isinstance(选项, 已解决的导出选项): self.dynamic_shapes = 选项.dynamic_shapes self.诊断选项 = 选项.诊断选项 self.模拟上下文 = 选项.模拟上下文 self.fx_tracer = 选项.fx_tracer self.ONNX 注册表 = 选项.onnx 注册表 self.onnx 函数分发器 = 选项.onnx 函数分发器 self.分解表 = 选项.分解表 self.诊断上下文 = 选项.诊断上下文 否则: T = 类型变量(T) def 解决(: T | , 备用: T | 可调用[] T]) -> T: 如果 value not : 返回 value 如果 可调用(备用): 返回 备用() 返回 回退 self.dynamic_shapes = 解决(选项.动态形状, 错误) self.诊断选项 = 解决( 选项.诊断选项, 诊断选项() ) self.fx_tracer = Dynamo 图提取器.动力导出() self.模拟上下文 = 解决(选项.模拟上下文, ) # type: ignore[arg-type] self.诊断上下文 = 诊断.诊断上下文( torch.onnx.dynamo_export, 火炬.__版本__, self.诊断选项, ) self.onnx_registry = 解决(选项.onnx_registry, Onnx 注册表()) self.分解表 = ( 分解表.创建 ONNX 友好分解表( # 类型:忽略[赋值] self.ONNX 注册表 ) ) 来自 torch.onnx._internal.fx 导入 onnxfunction_dispatcher self.onnxfunction_dispatcher = ( onnxfunction_dispatcher.OnnxFunctionDispatcher( self.onnx_registry, self.诊断上下文, ) ) key 目录(选项): 如果 not .以...开头(“_”): # 跳过私有属性 断言 有属性(self, ), f"未解决的选项 '"{}'"' @contextlib.contextmanager def 启用模拟模式(): 启用模拟模式,持续整个上下文过程。 内部它实例化一个 :class:`torch._subclasses.fake_tensor.FakeTensorMode` 上下文管理器 该管理器将用户输入和模型参数转换为 :class:`torch._subclasses.fake_tensor.FakeTensor` 一个 :class:`torch._subclasses.fake_tensor.FakeTensor` 是一个具有运行 PyTorch 代码能力的 :class:`torch.Tensor`,无需通过在 ``meta`` 设备上分配张量来实际进行计算。 因为没有在设备上实际分配数据,这个 API 允许在不实际执行所需的内存占用情况下初始化和导出大型模型。 由于没有在设备上实际分配数据,这个 API 允许在不实际执行所需的内存占用情况下初始化和导出大型模型。 由于没有在设备上实际分配数据,这个 API 允许在不实际执行所需的内存占用情况下初始化和导出大型模型。 非常推荐在导出模型时,如果模型太大无法放入内存,请使用模拟模式初始化模型。 该函数不支持 torch.onnx.export(..., dynamo=True, optimize=True)。 .. 注意:: 请在模型导出后,在函数外部调用 ONNXProgram.optimize()。 请在模型导出后,在函数外部调用 ONNXProgram.optimize()进行优化。 示例:: # xdoctest: +REQUIRES(env:TORCH_DOCTEST_ONNX) >>> 导入 torch >>> 类 MyModel(torch.nn.Module): # 带有参数的模型 ... def __init__(self) -> None: ... super().__init__() ... self.weight = torch.nn.Parameter(torch.tensor(42.0)) ... def forward(self, x): ... return self.weight + x >>> with torch.onnx.enable_fake_mode(): ... 当以模拟模式初始化时,模型的参数是模拟张量 ... 这些张量不占用内存,因此我们可以初始化大型模型 ... my_nn_module = MyModel() ... arg1 = torch.randn(2, 2, 2) >>> onnx_program = torch.onnx.export(my_nn_module, (arg1,), dynamo=True, optimize=False) >>> # 保存模型时不包含初始化器(仅架构) >>> onnx_program.save() ... \"my_model_without_initializers.onnx\", ... include_initializers=False, ... keep_initializers_as_inputs=True, ... ) >>> # 保存模型后应用具体权重,包含初始化器 >>> onnx_program.apply_weights({"weight": torch.tensor(42.0)}) >>> onnx_program.save("my_model_with_initializers.onnx") .. 警告:: 该 API 是实验性的,并且**不**向下兼容。 "源代码" 来自 torch._subclasses 导入 fake_tensor 来自 torch.fx.experimental.symbolic_shapes 导入 形状环境 # 这将覆盖由 `torch._dynamo.export`[1] 创建的内部 `FakeTensorMode` 实例。 # 最好保持它们(构造函数参数)同步,以保持相同的默认行为 # [1] `torch/_dynamo/output_graph.py::InstructionTranslator::OutputGraph.__init__` 仅当在 `FakeTensorMode` 中未调用 `torch.onnx.dynamo_export` 时,才允许混合假/实张量 这是因为模型可以在 `forward(self, *args, **kwargs)` 运行期间创建新的参数 模拟模式 = 伪造张量.假 Tensor 模式( allow_non_fake_inputs=not 火炬._守卫.检测伪造模式(), 形状环境=ShapeEnv( 允许标量输出=错误, 允许动态输出形状操作= ), ) 当用户在假模式下调用 `fake_model.load_state_dict(...)` 时需要这个补丁器 补丁器上下文 = 修补器.ONNXTorchPatcher() 模拟上下文 = ONNX 模拟上下文(模拟模式=模拟模式) 模拟模式, 修补器上下文: 产生 模拟上下文 模拟上下文.状态字典路径 = 元组( 修补器上下文.路径列表, ) # 类型:忽略[赋值] @deprecated( "torch.onnx.dynamo_export 自 2.7.0 版本开始已弃用。请使用 torch.onnx.export(..., dynamo=True)代替。", ) ONNX 运行时选项: """通过 ONNX Runtime 影响 ONNX 模型执行选项。""" 已弃用 请使用 ``torch.onnx.export(..., dynamo=True)`` 代替。 属性: ""session_options: ONNX Runtime 会话选项。"" ""execution_providers: 模型执行期间使用的 ONNX Runtime 执行提供者。"" ONNX Runtime 执行提供者选项。 "源代码" 会话选项: 序列[onnxruntime.SessionOptions] | None = ONNX Runtime 会话选项。 执行提供者: 序列[字符串 | 元组[字符串, 字典[任意, 任意]]] | = "ONNX Runtime 在模型执行期间使用的执行提供程序。" 执行提供程序选项: 序列[字典[任意, 任意]] | = None "ONNX Runtime 执行提供程序选项。" def 初始化( self, *, 会话选项: 序列[onnxruntime.SessionOptions] | = , 执行提供者: 序列[字符串 | 元组[字符串, 字典[任意, 任意]]] | = , 执行提供者选项: 序列[字典[任意, 任意]] | = , ): self.会话选项 = 会话选项 self.执行提供者 = 执行提供者 self.执行提供者选项 = 执行提供者选项 FX 图提取器(abc.ABC): """FX 图提取器引擎的抽象接口。 该类将 FX 提取逻辑从其他导出逻辑中隔离出来。 这使得可以复用不同 FX 图的单一 ONNX 导出器。 def 初始化(self) -> : 超级().初始化() self.输入适配器: 输入/输出适配器.输入适配器 = io 适配器.输入适配器() self.输出适配器: 离线适配器.输出适配器 = 离线适配器.输出适配器() @abc.抽象方法 def 生成 FX( self, 选项: 已解决的导出选项, 模型: 火炬.nn.模块 | 可调用, model_args: 序列[任意] 模型参数: 映射[字符串, 任意] ) -> 火炬.fx.图模块: 分析用户 ``模型`` 并生成 FX 图。 参数: 选项:导出选项。 模型:用户模型。 模型参数:模型的定位输入参数。 模型关键字输入参数 返回: 生成的 FX 图。 "源代码" ... # TODO: 设计遍历 API @abc.抽象方法 def 预导出步骤( self, 选项: 已解决导出选项, 原始模型: 火炬.nn.模块 | 可调用, 效果模块: 火炬.fx.图模块, fx_module_args: 序列[任意] ): 在 FX 图上应用预导出过程。 预导出过程是 FX 到 FX 图转换,使图 更适合 FX 到 ONNX 的转换。 例如,它可以用于展平模型输入/输出,添加显式 将到图的映射,替换/分解算子,函数化图等。 "源代码" ... 出口商: def 初始化( self, 选项: 已解决导出选项, 模型: 火炬.nn.模块 | 可调用, model_args: 序列[任意] 模型参数: 映射[字符串, 任意] ): self.选项 = 选项 断言 self.选项 not self.模型 = 模型 self.模型参数 = 模型参数 self.模型参数 = 模型参数 # TODO: https://github.com/pytorch/pytorch/issues/107714 # NOTE: FXSymbolicTracer 在这个断言中会失败,因为它没有使用 `enable_fake_mode` 来自 torch.onnx._internal.fx 导入 fx_symbolic_graph_extractor 如果 not isinstance( self.选项.fx_tracer, fx_symbolic_graph_extractor.FXSymbolicTracer ): self._assert_fake_tensor_mode() def 导出(self) -> _onnx_program.ONNX 程序: 来自 torch.export._trace 导入 ( 防止循环依赖 默认导出 Dynamo 配置, ) 将`import onnxscript`从`import torch`路径中延迟导入 https://github.com/pytorch/pytorch/issues/103764 来自 torch.onnx._internal.fx 导入 分解跳过 ( self.选项.诊断上下文, 分解跳过.启用分解跳过(self.选项), 火炬._dynamo.配置.补丁( dataclasses.asdict(默认导出 Dynamo 配置) ), ): 图模块 = self.选项.fx_tracer.生成 FX( self.选项, self.模型, self.model_args, self.模型参数 ) # TODO: 将`import onnxscript`从`import torch`路径中延迟导入 # https://github.com/pytorch/pytorch/issues/103764 来自 torch.onnx._internal.fx 导入 fx_onnx_interpreter fx_interpreter = fx_onnx_interpreter.FxOnnxInterpreter( 诊断上下文=self.选项.诊断上下文 ) onnxscript_graph = fx_interpreter.run( fx_graph_module=图模块, onnxfunction_dispatcher=self.选项.onnxfunction_dispatcher, ) # 注意:在 fake_mode 导出时,过滤掉具有虚假张量的初始化器。 # 否则,ONNX 导出器将失败:RuntimeError: basic_string::_M_construct null # 无效。 # 具体数据将在 `ONNXProgram.save` 后期初始化时填充。 如果 self.选项.模拟上下文 not : 初始化器包含真实张量: 字典[字符串, 火炬.张量] = {} ( 初始化器名称, 初始化器, ) onnxscript 图.初始化器.项目(): 如果 not isinstance(初始化器, 火炬.子类.假 Tensor): 使用真实张量的初始化器[初始化器名称] = 初始化器 onnxscript 图.初始化器 = 带真实张量的初始化器 # 导出 TorchScript 图到 ONNX ModelProto。 ONNX 模型 = onnxscript_graph.to_model_proto( self.选项.onnx_registry.opset 版本, ) ir_model = ir.serde.deserialize_model(onnx_model) try: ir_model = onnxscript_apis.优化(ir 模型) 除了 异常 作为 e: warnings.警告( "ONNXScript 优化器失败。跳过优化。" "\n\n \n\n请在 https://github.com/microsoft/onnxscript/issues 报告一个错误 f"\n\n \n\n详情:输入文本翻译为简体中文为:\n{e}" ) 返回 onnx 程序.ONNX 程序(索引模型, ) def _assert_fake_tensor_mode(self): 断言模型及其输入不包含伪造张量。 模型使用虚假输入/权重且未启用虚假模式 是否有任何虚假张量 = py 树.树中任何( lambda x: isinstance(x, 火炬.子类.假 Tensor), (self.model_args, self.模型参数), ) 是否有任何虚假参数或缓冲区 = 如果 isinstance(self.模型, 火炬.nn.模块): 包含任何伪造的参数或缓冲区 = py 树.树任何( lambda x: isinstance(x, 火炬.子类.假 Tensor), (self.模型.参数(), self.模型.缓冲区()), ) 如果 ( 包含任何伪造的张量 包含任何伪造的参数或缓冲区 ) not self.选项.模拟上下文: 提升 运行时错误( "无法在不启用模拟模式的情况下导出具有模拟输入/权重的模型。", ) # 案例二:具有非模拟输入/权重的模型且已启用模拟模式 是否包含任何非模拟张量 = py 树.树_任意( lambda x: isinstance(x, 火炬.张量) not isinstance(x, 火炬.子类.假 Tensor), (self.model_args, self.模型参数), ) 有任何非假参数或缓冲区 = 如果 isinstance(self.模型, 火炬.nn.模块): 有任何非假参数或缓冲区 = py 树.树_任意( lambda x: isinstance(x, 火炬.张量) not isinstance(x, 火炬.子类.假 Tensor), (self.模型.参数(), self.模型.缓冲区()), ) 如果 ( 包含任何非伪造张量 包含任何非伪造参数或缓冲区 ) self.选项.伪造上下文: 提升 运行时错误( "无法导出具有非伪造输入/权重并启用伪造模式的模型。", ) 不满足依赖错误(运行时错误): 当 ONNX 导出器依赖无法满足时引发。 def 初始化(self, 包名: 字符串, 消息: 字符串): 超级().初始化(消息) self.包名 = 包名 无效导出选项错误(运行时错误): 当用户为`:class:`ExportOptions`指定了无效值时引发。 def 断言依赖(导出选项: 已解决导出选项): 算子版本 = 导出选项.onnx_registry.算子版本 def 缺少包(包名: 字符串, exc_info: 记录日志._ExcInfoType): 消息 = ( f"请安装以下软件包"{包名} f"(例如 `python -m pip install"{包名} 。) ) 日志.致命(消息, exc_info=exc_info) 返回 不满足的依赖错误(包名, 消息) def 缺少 opset(包名: 字符串): 消息 = ( f"已安装的 `{包名}不支持指定的 ONNX 操作集版本 " f"版本"{opset 版本}安装一个更新的 `{包名}` 包或 " f指定一个较旧的 opset 版本。 ) 日志.致命(消息) 返回 不满足的依赖错误(包名, 消息) try: 导入 onnx 除了 导入错误 作为 e: 提升 缺少包(onnx, e) 来自 e 如果 onnx.定义.ONNX 操作集版本() < opset 版本: 提升 缺少 opset(onnx) try: PyTorch 在 CI 中运行 lintrunner 时未安装 onnxscript 导入 onnxscript # type: ignore[import] 除了 导入错误 作为 e: 提升 缺少包(onnxscript, e) 来自 e 如果 not isinstance( onnxscript.onnx_opset.all_opsets["", opset 版本)], onnx 脚本..Opset, ): 提升 缺少 Opset("onnx 脚本") def dynamo_export( 模型: 火炬.nn.模块 | 可调用, /, *model_args, 导出选项: 导出选项 | = , **模型参数, ) -> _onnx 程序.ONNX 程序: 将 torch.nn.Module 导出为 ONNX 图。 已弃用 请使用 ``torch.onnx.export(..., dynamo=True)`` 代替。 参数: 导出至 ONNX 的 PyTorch 模型。 model 参数:传递给`model`的位置参数。 model_kwargs:传递给`model`的关键字参数。 导出选项:影响导出到 ONNX 的选项。 返回: 导出 ONNX 模型的内存表示。 **示例 1 - 最简单的导出** :: class MyModel(torch.nn.Module): def __init__(self) -> None: super().__init__() self.linear = torch.nn.Linear(2, 2) def forward(self, x, bias=None): out = self.linear(x) out = out + bias return out model = MyModel() kwargs = {"bias": 3.0} args = (torch.randn(2, 2, 2),) onnx_program = torch.onnx.dynamo_export(model, *args, **kwargs).save( "my_simple_model.onnx" ) 示例 2 - 使用动态形状导出 :: 上一个模型可以导出为动态形状 export_options = torch.onnx.ExportOptions(dynamic_shapes=True) onnx_program = torch.onnx.dynamo_export( model, *args, **kwargs, export_options=export_options ) onnx_program.save("my_dynamic_model.onnx") 通过打印输入动态维度,我们可以看到输入形状不再是 (2,2,2) :: >>> print(onnx_program.model_proto.graph.input[0]) name: "arg0" 类型 { 张量类型 { 元素类型:1 shape { dim { 维度参数:"arg0_dim_0" } dim { dim_param: "arg0_dim_1" } dim { dim_param: "arg0_dim_2" } } } } "源代码" 如果 导出选项 not : resolved_export_options = ( 导出选项 如果 isinstance(导出选项, ResolvedExportOptions) 否则 已解决导出选项(导出选项, 模型=模型) ) 否则: 已解决导出选项 = 已解决导出选项(导出选项(), 模型=模型) _断言依赖(已解决导出选项) try: 来自 torch._dynamo 导入 配置 作为 _dynamo_config _dynamo_config.补丁(不发出运行时断言=True): 返回 导出器( 选项=已解析的导出选项, 模型=模型, model_args=model_args, 模型参数=模型参数, ).导出() 除了 异常 作为 e: sarif 报告路径 = 默认失败导出 SARIF 日志路径 解析的导出选项.诊断上下文.导出(sarif 报告路径) 消息 = ( f"导出模型到 ONNX 失败。正在生成 SARIF 报告。"{sarif 报告路径} SARIF 是静态分析工具输出格式的标准。 "SARIF 日志可以在 VS Code SARIF 查看器扩展中加载," "或者 SARIF 网页查看器(https://microsoft.github.io/sarif-web-component/)。" f"请在 PyTorch 的 GitHub 上报告一个错误:"{_PYTORCH_GITHUB_ISSUES_URL}" ) 提升 错误.ONNX 导出器错误(消息) 来自 e def 常见导出前处理( 选项: 已解决的导出选项, 原始模型: 火炬.nn.模块 | 可调用, 效果模块: 火炬.fx.图模块, fx 模块参数: 序列[任意] ): # TODO: 在此处导入以防止循环依赖 来自 torch.onnx._internal.fx 导入 分析, 通过 诊断上下文 = 选项.诊断上下文 将分解表应用于输入图。 模块 = 通行证.分解( 诊断上下文, fx 模块, 选项.分解表, 启用动态坐标轴=选项.动态形状, 允许伪造常量=选项.伪造上下文 not , ).run(*fx_module_args) # ONNX 不支持视图和修改。 # 函数化以获取无修改的语义等价图。 模块 = 通行证.函数化( 诊断上下文, 模块, 启用动态坐标轴=选项.动态形状, 允许伪造常量=选项.伪造上下文 not , ).run(*fx_module_args) # 输入变异在 `Functionalize` 阶段之后被检测和提炼。 # 由于 ONNX 推理不需要它们,因此可以移除。 模块 = 通行证.RemoveInputMutation(诊断上下文, 模块).run(*fx 模块参数) # ONNX 不支持(隐式)类型提升的概念。 # 在需要的地方显式插入类型转换。 模块 = 通行证.插入类型促销(诊断上下文, 模块).run() 分析.不支持的 Fx 节点分析( 诊断上下文, 模块, 选项.ONNX 函数调度器 ).分析(基础设施.等级.错误) 如果 isinstance(原始模型, 火炬.nn.模块): 模块 = 通行证.恢复参数和缓冲区名称( 诊断上下文, 模块, 原始模型 ).run() # 此操作应在导出前作为最后一个预导出步骤调用。 # 查看[注意:模块化步骤排序] 模块 = 通行证.模块化(诊断上下文, 模块).run() # ONNX 不支持 None 输入。在图构建过程中,所有 None 输入 # 都被移除。这里我们将此步骤注册到输入适配器中。 选项.fx_tracer.输入适配器.添加步骤(输入/输出适配器.删除 None 输入步骤()) # NOTE: 临时解决方案针对 https://github.com/pytorch/pytorch/issues/99534 # Dynamo 不支持非张量输入。 选项.fx_tracer.输入适配器.添加步骤(离线适配器.删除非张量输入步骤()) # ONNX 不支持复杂数据输入。在构建图的过程中,所有复杂数据输入 # 都会被转换为实数表示的输入。这里我们注册这个步骤以 输入/输出适配器 选项.fx_tracer.输入适配器.添加步骤( 输入输出适配器.将复杂类型转换为实表示法输入步骤() ) # ONNX 无法表示集合类型(例如,字典,元组的元组等),我们将集合展平并将每个元素注册为输出。 # 张量等),我们将集合展平并将每个元素注册为输出。 选项.fx_tracer.输出适配器.添加步骤(输入输出适配器.扁平化输出步骤()) 在 `FlattenOutputStep` 之后进行输出后处理步骤。 选项.fx_tracer.输出适配器.添加步骤( 输入/输出适配器.将复杂数据转换为实数表示输出步骤() ) 返回 模块

© 版权所有 PyTorch 贡献者。

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

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源