快捷键

torch.autograd.function 源代码

# mypy: 允许未类型化定义
导入 functools
导入 检查
导入 itertools
导入 警告
来自 集合 导入 OrderedDict
来自 打字 导入 任何, 可选
来自 typing_extensions 导入 已弃用

导入 火炬
导入 torch._C as _C
导入 torch._functorch as _functorch
导入 torch.utils.hooks as 钩子
来自 torch._C 导入 函数
来自 torch._functorch.autograd_function 导入 自定义函数调用


全部 = [
    函数上下文,
    向后 C 函数,
    "功能元",
    "功能",
    "一次可微分",
    "就地函数",
    "嵌套 IO 函数",
]

# 每个继承自 Function 的类的唯一 ID 提供者
# 在类定义期间在 FunctionMeta 中递增
AUTOGRAD_FUNCTION_COUNTER = itertools.数量()


# 之前称为:_ContextMethodMixin
 函数上下文:
[文档] def 保存用于回放(self, *张量: PyTorch.张量): r将给定的张量保存以供后续调用 :func:`~Function.backward`。 ``save_for_backward`` 应最多调用一次,在 :func:`setup_context` 或 :func:`forward` 方法中,并且仅针对张量。 所有打算在反向传播中使用的张量都应该被保存。 所有打算在反向传播中使用的张量都应该被保存。 使用 `save_for_backward`(而不是直接在 `ctx` 上)来防止 不正确的梯度计算和内存泄漏,并启用保存张量的钩子应用。 查看 :class:`torch.autograd.graph.saved_tensors_hooks`。 注意,如果中间张量,即既不是输入也不是输出的张量 forward 函数的输出在反向传播时不会被保存,您的自定义函数 可能不支持双重反向传播。 不支持双重反向传播的自定义函数应该使用 ``@once_differentiable`` 装饰其 backward 方法,以便执行 双向求导会引发错误。如果您想支持双向求导, 您可以选择根据输入在反向过程中重新计算中间变量, 或者将中间变量作为自定义函数的输出返回。请参阅 `双向求导教程 `_ `双向求导教程 `_ 更多详情请查看。 在 :func:`backward` 函数中,可以通过 :attr:`saved_tensors` 属性访问保存的张量。 在将它们返回给用户之前,会进行检查以确保它们没有被用于任何修改其内容的就地操作。 属性。在返回之前,会检查它们是否被用于任何修改其内容的就地操作。 参数也可以是 `None`。这是一个无操作。 更多关于如何使用此方法的详细信息,请参阅 :ref:`扩展 autograd`。 示例:: >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_AUTOGRAD) >>> class Func(Function): >>> @staticmethod >>> def forward(ctx, x: torch.Tensor, y: torch.Tensor, z: int): >>> w = x * z >>> out = x * y + y * z + w * y >>> ctx.save_for_backward(x, y, w, out) >>> ctx.z = z # z 不是张量 >>> return out ... >>> @staticmethod >>> @once_differentiable >>> def backward(ctx, grad_out): >>> x, y, w, out = ctx.saved_tensors >>> z = ctx.z >>> gx = grad_out * (y + y * z) >>> gy = grad_out * (x + z + w) >>> gz = None >>> return gx, gy, gz ... >>> a = torch.tensor(1., requires_grad=True, dtype=torch.double) >>> b = torch.tensor(2., requires_grad=True, dtype=torch.double) >>> c = 4 >>> d = Func.apply(a, b, c) """ self.保存 = 张量
def 保存以供转发(self, *张量: PyTorch.张量): r将给定的张量保存,以供将来调用 :func:`~Function.jvp` 的调用。 ``save_for_forward`` 应最多调用一次,无论是在 ... `setup_context` 或 `forward` 方法,以及所有参数 应该是张量。 在 `jvp` 中,可以通过 `saved_tensors` 属性访问已保存的对象。 属性。 参数也可以是 `None`。这是一个无操作。 更多关于如何使用此方法的详细信息,请参阅 :ref:`扩展 autograd`。 示例:: >>> # xdoctest: +SKIP >>> class Func(torch.autograd.Function): >>> @staticmethod >>> def forward(ctx, x: torch.Tensor, y: torch.Tensor, z: int): >>> ctx.save_for_backward(x, y) >>> ctx.save_for_forward(x, y) >>> ctx.z = z >>> 返回 x * y * z ... >>> @staticmethod >>> def jvp(ctx, x_t, y_t, _): >>> x, y = ctx.saved_tensors >>> z = ctx.z >>> return z * (y * x_t + x * y_t) ... >>> @staticmethod >>> def vjp(ctx, grad_out): >>> x, y = ctx.saved_tensors >>> z = ctx.z >>> return z * grad_out * y, z * grad_out * x, None ... >>> a = torch.tensor(1., requires_grad=True, dtype=torch.double) >>> t = torch.tensor(1., dtype=torch.double) >>> b = torch.tensor(2., requires_grad=True, dtype=torch.double) >>> c = 4 ... >>> with fwAD.dual_level(): >>> a_dual = fwAD.make_dual(a, t) >>> d = Func.apply(a_dual, b, c) """ for 张量 张量: 断言 isinstance(张量, PyTorch.张量) 或者 张量 , ( "save_for_forward 期望所有参数都是张量;你应该 " "将非张量作为 ctx 的属性保存。" ) self.保存以供转发 = 张量
[文档] def mark_dirty(self, *args: torch.Tensor): r"""将给定的张量标记为就地操作中的已修改。 这应该在 :func:`setup_context` 中最多调用一次。 或:func:`forward` 方法,所有参数应为输入。 每个在调用 :func:`forward` 中就地修改的张量 应传递给此函数,以确保我们检查的正确性。 它无关紧要,函数是在调用之前还是之后 修改。 示例:: >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_AUTOGRAD) >>> class Inplace(函数): >>> @staticmethod >>> def forward(ctx, x): >>> x_npy = x.numpy() # x_npy 与 x 共享存储 >>> x_npy += 1 >>> ctx.mark_dirty(x) >>> 返回 x >>> >>> @staticmethod >>> @once_differentiable >>> def backward(ctx, grad_output): >>> return grad_output >>> >>> a = torch.tensor(1., requires_grad=True, dtype=torch.double).clone() >>> b = a * a >>> Inplace.apply(a) # 这会导致错误的梯度! >>> # 但引擎不知道,除非我们标记为脏 >>> # xdoctest: +SKIP >>> b.backward() # 运行时错误:所需的变量之一在就地操作中被修改以进行梯度计算 >>> # 计算过程中所需的变量已被就地操作修改 """ self.dirty_tensors = args
@deprecated( "`mark_shared_storage` 已弃用。" 具有共享存储的张量会自动跟踪。 注意,对 `set_()` 的调用不会被跟踪。, 分类
=未来警告, ) def mark_shared_storage(self, *pairs): 通过
[文档] def mark_non_differentiable(self, *args: torch.Tensor): r"""标记输出为不可微分。 这应该在 :func:`setup_context` 中最多调用一次, 或:func:`forward` 方法,所有参数应为张量输出。 这将标记输出不需要梯度,增加 反向计算的效率。您仍然需要接受梯度 对于每个输出在::meth:`~Function.backward`中,但它始终会 与相应输出的形状相同的零张量 例如,用于从排序中返回的索引。请参见示例: 这用于例如从排序中返回的索引。请参见示例: class Func(Function): >>> @staticmethod >>> def forward(ctx, x): >>> sorted, idx = x.sort() >>> ctx.mark_non_differentiable(idx) >>> ctx.save_for_backward(x, idx) >>> return sorted, idx >>> >>> @staticmethod >>> @once_differentiable >>> def backward(ctx, g1, g2): # 仍然需要接受 g2 >>> x, idx = ctx.saved_tensors >>> grad_input = torch.zeros_like(x) >>> grad_input.index_add_(0, idx, g1) >>> return grad_input """ self.non_differentiable = args
[文档] def set_materialize_grads(self, value: bool): r"""设置是否实例化梯度张量。默认为 ``True``。 应仅从 :func:`setup_context` 或 func:`forward` 方法中调用。 如果为 ``True``,未定义的梯度张量将被扩展为全零的张量 在调用 :func:`backward` 和 :func:`jvp` 方法之前。 示例:: >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_AUTOGRAD) >>> class SimpleFunc(Function): >>> @staticmethod >>> def forward(ctx, x): >>> return x.clone(), x.clone() >>> >>> @staticmethod >>> @once_differentiable >>> def backward(ctx, g1, g2): >>> 返回 g1 + g2 # 无需检查 None >>> >>> 我们修改 SimpleFunc 以处理非物化梯度输出 >>> class Func(Function): >>> @staticmethod >>> def forward(ctx, x): >>> ctx.set_materialize_grads(False) >>> ctx.save_for_backward(x) >>> 返回 x 的克隆,x 的克隆 >>> >>> @staticmethod >>> @once_differentiable >>> def backward(ctx, g1, g2): >>> x, = ctx.saved_tensors >>> grad_input = torch.zeros_like(x) >>> if g1 is not None: # 我们现在必须检查 None >>> grad_input += g1 >>> 如果 g2 不为 None: >>> grad_input += g2 >>> 返回 grad_input >>> >>> a = torch.tensor(1., requires_grad=True) >>> b, _ = Func.apply(a) # 诱导 g2 未定义 """ self.materialize_grads = value
# DO NOT USE: 仅用于加载旧序列化模型 _ContextMethodMixin = 函数上下文 _HookMixin: @staticmethod def _register_hook(后退钩子, hook): 如果
backward_hooks : backward_hooks = 有序字典() handle = 钩子.可移除句柄(后退钩子) 后退钩子[处理.id] = 钩子 返回 后退钩子, handle
[文档]类 BackwardCFunction(_C._FunctionBase, FunctionCtx, _HookMixin): r""" 这个类用于内部自动微分工作。请勿使用。 """
[文档] def apply(self, *args): r""" 应用在执行此节点时使用的反向方法 ```python # 输入文本 input_text = '"""' # 翻译函数(此处为示例,实际翻译功能需调用真实的翻译 API) def translate_to_simplified_chinese(text): # 假设的翻译结果 return text # 输出翻译结果 translated_text = translate_to_simplified_chinese(input_text) print(translated_text) ``` # _forward_cls 由派生类定义 用户应定义反向或 vjp,但不能同时定义两者。 backward_fn = self._forward_cls.backward # 忽略属性定义 vjp_fn = self._forward_cls.vjp # 忽略属性定义 if backward_fn is not Function.backward and vjp_fn is not Function.vjp: raise RuntimeError( 实现自定义函数的“反向”和“vjp”功能 不允许同时实现这两个功能。您应该只实现其中一个 的功能。 ) user_fn = vjp_fn if vjp_fn is not Function.vjp else backward_fn return user_fn(self, *args)
[文档] def apply_jvp(self, *args): r""" 在执行前向模式自动微分时使用的方法 """ # _forward_cls 由派生类定义 return self._forward_cls.jvp(self, *args) # 类型:忽略[属性定义]
def _compiled_autograd_key(self): return self._forward_cls._compiled_autograd_key(self) # 类型:忽略[属性定义]
函数元信息(类型): 函数元类。 这个元类设置了以下属性: _backward_cls:对应于微分操作的函数类 此函数的版本(由该函数动态生成) 元类 """ def __init__(, 名称, bases, 属性): backward_fn = 类型( 名称 + "向后", (向后 C 函数,), {"_forward_cls": } ) backward_fn.自动微分函数 ID = 下一(AUTOGRAD_FUNCTION_COUNTER) # 类型:忽略[已定义] backward_fn._bw_module = # 类型:忽略[已定义] 如果 getattr(, _lazy_backward_info, ): backward_fn._bw_module = ._lazy_backward_info.bw_module # 类型:忽略[已定义] ._backward_cls = backward_fn 超级().__init__(名称, bases, 属性) 单级函数( _C._函数基类, 函数上下文, _HookMixin, 元类=函数元信息 ): @staticmethod def 前向(*参数: 任何, **kwargs: 任何) -> 任何: r定义自定义自动微分函数的前向操作。 此函数必须由所有子类重写。 定义前向有两种方式: 使用 1(组合前向和 ctx): @staticmethod def forward(ctx: Any, *args: Any, **kwargs: Any) -> Any: 通过 - 它必须接受一个上下文 ctx 作为第一个参数,后面可以跟任何 参数数量(张量或其他类型)。 - 更多详情请参阅 :ref:`结合前向上下文` 使用方法 2(分离前向和 ctx):: @staticmethod def forward(*args: Any, **kwargs: Any) -> Any: 通过 @staticmethod def setup_context(ctx: Any, inputs: Tuple[Any, ...], output: Any) -> None: 通过 前向函数不再接受 ctx 参数。 取而代之,您必须重写 :meth:`torch.autograd.Function.setup_context` 静态方法来处理设置 ``ctx`` 对象。 ``output`` 是前向的输出,``inputs`` 是输入的元组 到前向的。 - 更多详情请参阅 :ref:`extending-autograd` 上下文可以用来存储任意数据,然后 在反向传播过程中检索。张量不应直接存储在 `ctx` 上(尽管这目前没有强制执行,以保持向后兼容)。相反,如果张量打算用于反向传播,则应使用 :func:`ctx.save_for_backward` 保存。 直接在 `ctx` 上(尽管这目前没有强制执行,以保持向后兼容)。相反,张量应保存为 :func:`ctx.save_for_backward`,如果它们打算用于反向传播。 (尽管这目前没有强制执行,以保持向后兼容)。相反,如果张量打算用于反向传播,则应使用 :func:`ctx.save_for_backward` 保存。 如果它们打算用于反向传播,则应使用 :func:`ctx.save_for_backward` 保存。 ``backward``(等价于 ``vjp``)或 :func:`ctx.save_for_forward` 如果它们打算用于 ``jvp``。 """ 抛出 不支持的操作异常( "你必须实现自定义 autograd.Function 的前向函数。" ) @staticmethod def 设置上下文(ctx: 任何, 输入: 元组[Any, ...] 输出: 任何) -> 任何: r"""定义 autograd.Function 的前向传递有两种方式。 Either: 1. 使用签名 `forward(ctx, *args, **kwargs)` 覆盖 forward。 `setup_context` 未被覆盖。设置 ctx 用于 backward 发生在 `forward` 内部。 发生在 `forward` 内部。 2. 使用签名 `forward(*args, **kwargs)` 覆盖 forward 并 覆盖 `setup_context`。设置 ctx 以支持向后操作 在 `setup_context` 内部(与在 `forward` 内部相对) 请参阅 :meth:`torch.autograd.Function.forward` 和 :ref:`extending-autograd` 以获取更多详细信息。 """ 抛出 不支持的操作异常("setup_context 尚未实现。") @staticmethod def 反向(ctx: 任何, *grad_outputs: 任何) -> 任何: r定义使用向后模式自动微分对操作进行求导的公式。 此函数必须由所有子类重写。 定义此函数等同于定义 ``vjp`` 函数。 它必须接受一个上下文 :attr:`ctx` 作为第一个参数,后面可以跟 任意多个输出,这些输出与 :func:`forward` 返回的相同(对于非张量输出,将传递 None), 逗号分隔,逗号后面可以跟任意多个输出,这些输出与 :func:`forward` 返回的相同(对于非张量输出,将传递 None), 应返回与输入数量相同的张量, func:`forward`。每个参数是相对于给定输出的梯度, 每个返回值应该是相对于相应输入的梯度。 如果一个输入不是张量,或者是一个非张量的张量, 需要梯度时,您可以为该输入传递 None 作为梯度。 上下文可以用来检索在正向传播过程中保存的张量 通过。它还有一个属性::attr:`ctx.needs_input_grad` 作为元组 表示每个输入是否需要梯度的布尔值。例如: `:func:`backward` 将设置 `ctx.needs_input_grad[0] = True`,如果 `:func:`forward` 的第一个输入需要计算关于输出的梯度。 第一个输入需要计算关于输出的梯度。 您必须实现 `backward` 或 `vjp` 方法之一。 """ 抛出 不支持的操作异常( "你必须实现 `backward` 或 `vjp` 方法之一。" "自定义 autograd.Function 以使用它进行反向传播" "模式 AD。" ) # vjp 和 backward 是彼此的别名 vjp = 向后 @staticmethod def jvp(ctx: 任何, *梯度输入: 任何) -> 任何: r定义使用前向模式自动微分进行操作微分的公式。 此函数必须由所有子类重写。 它必须接受一个上下文 :attr:`ctx` 作为第一个参数,后面可以跟 如 :func:`forward` 所获得的那么多输入(将传递 None) 对于前向函数的非张量输入), 应返回与输出数量相同的张量, func:`forward`。每个参数是相对于给定输入的梯度, 每个返回值应该是相对于相应输入的梯度。 相应的输出。如果输出不是张量或者该函数对输出不可微分,你可以为该输入传递 None 作为梯度。 你可以使用:attr:`ctx`对象从正向传递任何值到这个函数。 你可以传递 None 作为该输入的梯度。 你可以使用:attr:`ctx`对象从正向传递任何值到这个函数。 函数。 """ 抛出 不支持的操作异常( 您必须实现自定义的 jvp 函数 自动微分的前向模式 AD 使用的 autograd.Function。 )
[文档] 函数(单级函数): r基础类,用于创建自定义 `autograd.Function`。 创建自定义 `autograd.Function`,继承此类并实现 the :meth:`forward` 和 :meth:`backward` 静态方法。然后,为了使用您的自定义 在正向传播中,调用类的 ``apply`` 方法。不要调用 直接使用 :meth:`forward` 方法。 确保正确性和最佳性能,请确保您正在调用正确的 ``ctx`` 上的正确方法,并使用 :func:`torch.autograd.gradcheck` 验证您的反向函数。 使用 :func:`torch.autograd.gradcheck` 验证您的反向函数。 查看更多关于如何使用此类的详细信息,请参阅::ref:`extending-autograd`。 示例: >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_AUTOGRAD) >>> class Exp(Function): >>> @staticmethod >>> def forward(ctx, i): >>> result = i.exp() >>> ctx.save_for_backward(result) >>> return result ... >>> @staticmethod >>> def backward(ctx, grad_output): >>> result, = ctx.saved_tensors >>> return grad_output * result ... >>> # 使用它,请调用 apply 方法: >>> # xdoctest: +SKIP >>> output = Exp.apply(input) """ def __init__(self, *参数, **kwargs): 警告.警告( f"{self.}应该不被实例化。自动微分函数的方法 都是静态的,所以你应该在类本身上调用它们。 实例化一个 autograd 函数将引发一个 错误出现在 PyTorch 的将来版本中。, 弃用警告, 栈级别=2, ) def __调用__(self, *参数, **kwargs): 抛出 运行时错误( 遗留的具有非静态前向方法的 autograd 函数已弃用。 请使用具有静态前向方法的新的 autograd 函数。 "(示例:https://pytorch.org/docs/stable/autograd.html#torch.autograd.Function)" ) "" 指定 PyTorch 是否尝试自动生成布尔值 func:`torch.vmap` 对此 autograd.Function 的支持。您可能需要将其设置为 仅当此 autograd.Function 的 forward、backward 和 jvp(如果有的话)为 True 存在(exist)的函数是用 PyTorch 操作编写的;否则,请覆盖 使用 :meth:`torch.autograd.Function.vmap` 添加对 :func:`torch.vmap` 的支持。 更多详情请参阅 :ref:`func-autograd-function`。 """ generate_vmap_rule =
[文档] @staticmethod def vmap(info, in_dims, *args): 在 :func:`torch.vmap` 下定义此 autograd.Function 的行为。 为了使 :func:`torch.autograd.Function` 支持 `torch.vmap`,你必须重写这个静态方法,或者将`generate_vmap_rule`设置为`True`(你不能两者都做)。 如果你选择重写这个 staticmethod:它必须接受一个`info`对象作为第一个参数。`info.batch_size` 如果你选择重写这个静态方法:它必须接受 - 一个`info`对象作为第一个参数。`info.batch_size` 指定了进行 vmapped 的维度大小, 而 `info.randomness` 是传递给 :func:`torch.vmap` 的随机性选项, func:`torch.vmap`。 - 作为第二个参数的 `in_dims` 元组。 对于每个 arg 在`args`中,`in_dims`都有一个对应的 ``Optional[int]``. 它是 ``None`` 如果参数不是一个张量或者 参数没有被映射到虚拟内存中,否则它是一个整数 指定 Tensor 的哪个维度正在被 vmapped。 `*args` 与 :meth:`~Function.forward` 的参数相同。 vmap 静态方法的返回值是一个 `(output, out_dims)` 的元组。 与 `in_dims` 类似,`out_dims` 应该与 `output` 具有相同的结构。 `output` 和包含一个 `out_dim` 的结构,每个 `out_dim` 指定每个输出是否 输出具有 vmapped 维度及其索引。 请参阅::ref:`func-autograd-function` 了解更多详情。 ```python # 输入文本 input_text = '"""' # 翻译函数(此处为示例,实际翻译功能需调用真实的翻译 API) def translate_to_simplified_chinese(text): # 假设的翻译结果 return text # 输出翻译结果 translated_text = translate_to_simplified_chinese(input_text) print(translated_text) ``` 引发未实现错误(NotImplementedError) 使用 autograd.Function 与 vmap 一起使用时,你必须要么覆盖 " vmap 静态方法或设置 generate_vmap_rule=True。 )
@classmethod def 应用
(, *参数, **kwargs): def 绑定默认参数(函数, *参数, **kwargs): 签名 = 检查.签名(函数) 绑定参数 = 签名.绑定(*参数, **kwargs) 绑定参数.应用默认值() 返回 绑定参数.args 是否已定义设置上下文 = _是否已定义设置上下文(.设置上下文) 如果 是否已定义设置上下文: args = 绑定默认参数(.前向, *参数, **kwargs) 如果 PyTorch._C.都是 functorch 转换激活(): # 注意:[functorch vjp 和 autograd 交互] args = _functorch.工具.解包无效包装器(参数) 返回 超级().应用(*参数, **kwargs) # 类型:忽略[杂项] 如果 是否已定义设置上下文: 抛出 运行时错误( 为了使用 functorch 转换与 autograd.Function 一起 (vmap, grad, jvp, jacrev, ...), 必须重写 setup_context staticmethod. 更多详情,请参阅 https://pytorch.org/docs/main/notes/扩展.func.html ) 返回 自定义函数调用(, *参数, **kwargs) @staticmethod def _编译自动微分键(ctx): 返回 (ctx._自动微分函数 ID,)
def _是否已定义设置上下文(函数): 返回 fn != 单级函数.设置上下文
[文档]def 一次可微分(fn): @functools.wraps(fn) def wrapper(ctx, *args): with torch.no_grad(): outputs = fn(ctx, *args) if not torch.is_grad_enabled(): 返回输出 如果任何输入具有 requires_grad=True,我们强制输出 需要具有 requires_grad=True 但指向一个抛出异常的 grad_fn # 双向传播过程中的错误信息。 # XXX:这只是一个对 requires_grad 的近似——没有办法 # 确定如果 fn 没有使用 ctx.saved_tensors,那么即使没有参数,某些 Tensor 也可能需要梯度。 # 不幸的是,这会导致意外的错误信息(“没有节点”) # “Unfortunately, this leads to unexpected error messages ("no nodes") # 需要计算梯度"),但我没有更好的主意。 这些函数在反向传播中无论如何都会引发错误。 requires_grad = any( isinstance(arg, torch.Tensor) and arg.requires_grad for arg in args 翻译:arg 属于 torch.Tensor 类型且 arg 需要梯度,对于 args 中的每个 arg ) 如果不需要梯度: 返回输出 如果输出不是元组类型: outputs = (outputs,) err_fn = _functions.DelayedError( 尝试对标记了 @once_differentiable 的函数进行两次微分 with @once_differentiable len(outputs), ) # 创建每个需要 requires_grad=True 的输出的别名。我们需要 # 至少一个输入到 err_fn 需要梯度,以便 # output will have a grad_fn. def fake_requires_grad(var): if var is not None: var = var.detach() var.requires_grad = True return var return err_fn(*[fake_requires_grad(v) for v in outputs]) return wrapper
[文档]class InplaceFunction(Function): r""" 这个类仅为了向后兼容而存在。 对于任何新的用例,请使用 :class:`Function` 而不是这个。 """ """ def __init__(self, inplace=False): super().__init__() self.inplace = inplace
def _nested_map(condition, 函数
, 条件消息=): def _map(对象): 如果 condition(对象): 返回 函数(对象) 如果...否则 对象 : 返回 如果...否则 isinstance(对象, (列表, 元组)): 已映射 = (_map(x) for x 对象) 如果 有属性(对象, "_字段"): # obj 是命名元组 返回 类型(对象)(*映射) 返回 类型(对象)(映射) 如果...否则 isinstance(对象, 字典): 返回 {x: _map(对象[x]) for x 对象} 否则: 抛出 值错误( "自动嵌套不知道如何处理 " "一个输入对象类型为" + PyTorch.类型名(对象) + ( "。支持的类型:" + 条件消息 + ",或它们的列表/元组" 如果 条件消息 否则 请提供需要翻译的文本 ) ) 返回 地图 def _jit_unwrap_structured(对象): 如果 有属性(对象, "_jit_unwrap"): 返回 对象._jit_unwrap() 返回 对象 def 迭代过滤(condition, 允许未知=False, 条件消息=, 转换=): def _迭代(对象): 如果 转换 : 对象 = 转换(对象) 如果 condition(对象): 产生 对象 如果...否则 对象 : 返回 如果...否则 isinstance(对象, (列表, 元组)): for o 对象: yield from _迭代(o) 如果...否则 isinstance(对象, 字典): 仅接受原始键类型,因此无需检查它们 for o 对象.(): yield from _迭代(o) 如果...否则 允许未知: 产生 对象 否则: 抛出 值错误( "自动嵌套不知道如何处理 " "一个输入对象类型为" + PyTorch.类型名(对象) + ( "。支持的类型:" + 条件消息 + ",或它们的列表/元组" 如果 条件消息 否则 请提供需要翻译的文本 ) ) 返回 _迭代 def _unflatten(输入, proto): # 将列表或元组输入展开成嵌套列表/元组结构 # specified by proto def unflatten_helper(输入, proto): 资源: 列表[可选[PyTorch.张量]] = 输入文本为空,请提供需要翻译的文本 如果 有属性(proto, _jit_wrap): 返回 proto._jit_wrap(输入) 如果 isinstance(proto, (列表, 元组)): 返回 输入[0] 输入[1] for e proto: 如果 e : 资源.添加(e) 否则: res_e, 输入 = unflatten_helper(输入, e) 资源.添加(res_e) 返回 类型(proto)(资源), 输入 返回 unflatten_helper(输入, proto)]0] 迭代_jit_values = 迭代过滤( Lambda 函数 o: o 或者 isinstance(o, PyTorch._C.), 条件消息=JIT 的值或 None, ) _iter_tensors = 迭代过滤( Lambda 函数 x: isinstance(x, PyTorch.张量), 条件消息=张量, 转换=_jit_unwrap_structured, ) _iter_tensors_permissive = 迭代过滤( Lambda 函数 x: isinstance(x, PyTorch.张量), 允许未知=True, 条件消息=张量(宽松), ) _iter_None_tensors = 迭代过滤( Lambda 函数 o: o 或者 isinstance(o, PyTorch.张量), 条件消息="张量或无" ) _map_tensor_data = _nested_map( Lambda 函数 x: isinstance(x, PyTorch.张量), Lambda 函数 o: o.数据, 条件消息=张量 )
[文档] 嵌套 IO 函数(函数): r"" 这个类仅为了向后兼容而存在。 请使用 :class:`Function` 而不是这个,以用于任何新的用例。 """ 因为这些函数在这里被声明为 '@staticmethod',所以需要 'type: ignore' 语句 超类(Function)是静态方法,但在这里是实例方法,mypy 报告为不兼容 def _执行前向(self, *输入): self._nested_input = 输入 平面输入 = 元组(_迭代张量(输入)) 平面输出 = 超级()._执行前向(*平面输入) # 类型:忽略[杂项] 嵌套张量 = _unflatten(平面输出, self._嵌套输出) 返回 嵌套张量 def 执行反向操作(self, 渐变, 保留变量): self.保留变量 = 保留变量 结果 = 超级().执行反向操作(渐变, 保留变量) # 类型:忽略[杂项] 如果 保留变量: 删除 self._嵌套输出 删除 self.保存嵌套 返回 结果
[文档] def backward(self, *gradients: Any) -> Any: # type: ignore[override] r""" 共享反向工具。 """ nested_gradients = _unflatten(gradients, self._nested_output) result = self.backward_extended(*nested_gradients) # 忽略[func-returns-value] return tuple(_iter_None_tensors(result))
__call__ = _do_forward
[文档] def forward(self, *args: Any) -> Any: # type: ignore[override] r""" 共享前向实用程序。 "" nested_tensors = _map_tensor_data(self._nested_input) result = self.forward_extended(*nested_tensors) # 忽略[func-returns-value]类型 删除 self._nested_input self._nested_output = result 返回 tuple(_iter_tensors(result))
[文档] def save_for_backward(self, *args: Any) -> None: r""" 查看 :meth:`Function.save_for_backward`。 """ self.to_save = tuple(_iter_tensors(args)) self._to_save_nested = args
@property def 已保存的张量(self): r"" 查看 :meth:`Function.saved_tensors`。 """ 平坦张量
= 超级().保存的张量 # 类型:忽略[杂项] 返回 _unflatten(flat_tensors, self._to_save_nested)
[文档] def mark_dirty(self, *args: Any, **kwargs: Any) -> None: r""" 查看 :meth:`Function.mark_dirty`。 """ self.dirty_tensors = tuple(_iter_tensors((args, kwargs)))
[文档] def mark_non_differentiable(self, *args: Any, **kwargs: Any) -> None: r""" 查看 :meth:`Function.mark_non_differentiable`. """ self.non_differentiable = tuple(_iter_tensors((args, kwargs)))
[文档] def forward_extended(self, *input: Any) -> None: r""" 用户自定义的前向函数。 "``" 引发未实现异常
[文档] def backward_extended(self, *grad_output: Any) -> None: r""" 用户自定义反向操作。 """ 引发未实现错误

© 版权所有 PyTorch 贡献者。

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

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源