• 文档 >
  • 自动微分包 - torch.autograd
快捷方式

自动微分包 - torch.autograd

torch.autograd 提供了实现任意标量值函数自动微分的类和函数。

它对现有代码的改动最小 - 你只需要用 requires_grad=True 关键字声明需要计算梯度的 Tensor。目前,我们仅支持浮点 Tensor 类型( half, float, double 和 bfloat16)和复数 Tensor 类型(cfloat, cdouble)的自动微分。

backward

计算给定张量相对于图叶节点的梯度之和。

grad

计算并返回输出相对于输入的梯度之和。

前向模式自动微分

警告

此 API 处于 Beta 阶段。尽管函数签名极不可能改变,但在被认为是稳定版本之前,计划改进算子覆盖率。

有关如何使用此 API 的详细步骤,请参阅前向模式 AD 教程

forward_ad.dual_level

用于前向 AD 的上下文管理器,所有前向 AD 计算必须在 dual_level 上下文内发生。

forward_ad.make_dual

将张量值与其切线相关联,以创建用于前向 AD 梯度计算的“对偶张量”。

forward_ad.unpack_dual

解包“对偶张量”,获取其张量值和前向 AD 梯度。

forward_ad.enter_dual_level

进入新的前向梯度级别。

forward_ad.exit_dual_level

退出前向梯度级别。

forward_ad.UnpackedDualTensor

unpack_dual() 返回的 Namedtuple,包含对偶张量的原始分量和切线分量。

函数式高级 API

警告

此 API 处于 Beta 阶段。尽管函数签名极不可能改变,但在被认为是稳定版本之前,计划进行重大的性能改进。

本节包含基于上述基本 API 构建的自动微分高级 API,允许您计算雅可比矩阵、海森矩阵等。

此 API 适用于用户提供的函数,这些函数仅将 Tensor 作为输入并仅返回 Tensor。如果您的函数接受非 Tensor 的其他参数或未设置 requires_grad 的 Tensor,您可以使用 lambda 表达式捕获它们。例如,对于一个函数 f,它接受三个输入:一个需要计算雅可比矩阵的 Tensor,一个应视为常量的 Tensor,以及一个布尔标志 f(input, constant, flag=flag),您可以将其用作 functional.jacobian(lambda x: f(x, constant, flag=flag), input)

functional.jacobian

计算给定函数的雅可比矩阵。

functional.hessian

计算给定标量函数的海森矩阵。

functional.vjp

计算向量 v 与给定函数在输入点处的雅可比矩阵的点积。

functional.jvp

计算给定函数在输入点处的雅可比矩阵与向量 v 的点积。

functional.vhp

计算向量 v 与给定标量函数在指定点处的海森矩阵的点积。

functional.hvp

计算标量函数的海森矩阵与向量 v 在指定点处的点积。

局部禁用梯度计算

有关 no-grad 和推理模式之间的差异以及可能与两者混淆的其他相关机制的更多信息,请参阅局部禁用梯度计算。另请参阅局部禁用梯度计算以获取可用于局部禁用梯度的函数列表。

默认梯度布局

当非稀疏 paramtorch.autograd.backward()torch.Tensor.backward() 期间接收到非稀疏梯度时,param.grad 按如下方式累积。

如果 param.grad 最初是 None

  1. 如果 param 的内存是不重叠且稠密的,则创建的 .grad 的跨步与 param 匹配(因此与 param 的布局匹配)。

  2. 否则,创建的 .grad 的跨步是按行主序连续的。

如果 param 已经有一个非稀疏的 .grad 属性

  1. 如果 create_graph=Falsebackward() 会就地累积到 .grad 中,从而保留其跨步。

  2. 如果 create_graph=Truebackward() 会用一个新的张量 .grad + new grad 替换 .grad,该张量试图(但不保证)匹配已存在的 .grad 的跨步。

默认行为(在第一次 backward() 之前让 .gradNone,以便其布局根据第 1 或第 2 条创建,并根据第 3 或第 4 条随时间保留)推荐用于获得最佳性能。调用 model.zero_grad()optimizer.zero_grad() 不会影响 .grad 布局。

事实上,在每个累积阶段之前将所有 .grad 重置为 None,例如:

for iterations...
    ...
    for param in model.parameters():
        param.grad = None
    loss.backward()

这样它们每次都会根据第 1 或第 2 条重新创建,是 model.zero_grad()optimizer.zero_grad() 的一个有效替代方案,可能会改善某些网络的性能。

手动梯度布局

如果您需要手动控制 .grad 的跨步,请在第一次 backward() 之前将一个具有所需跨步的零张量赋值给 param.grad =,并且永远不要将其重置为 None。只要 create_graph=False,第 3 条就保证您的布局得到保留。第 4 条表明即使 create_graph=True,您的布局也可能得到保留。

张量的就地操作

在自动微分中支持就地操作是一个难题,在大多数情况下我们不鼓励使用它们。自动微分的激进缓冲区释放和重用使其非常高效,就地操作实际上显著降低内存使用的情况非常少。除非您处于内存压力很大的情况下,否则可能永远不需要使用它们。

就地操作正确性检查

所有 Tensor 都跟踪应用到其上的就地操作,如果实现检测到某个张量在一个函数中被保存用于反向传播,但之后被就地修改,一旦反向传播开始,就会引发错误。这确保了如果您使用就地函数且没有看到任何错误,您可以确信计算出的梯度是正确的。

Variable (已弃用)

警告

Variable API 已被弃用:使用张量进行自动微分不再需要 Variable。自动微分自动支持设置了 requires_gradTrue 的 Tensor。下面是关于已更改内容的快速指南。

  • Variable(tensor)Variable(tensor, requires_grad) 仍然按预期工作,但它们返回的是 Tensor 而不是 Variable。

  • var.datatensor.data 相同。

  • 现在 var.backward(), var.detach(), var.register_hook() 等方法也可用于张量,方法名相同。

此外,现在可以使用工厂方法(如 torch.randn()torch.zeros()torch.ones() 等)创建 requires_grad=True 的张量,如下所示:

autograd_tensor = torch.randn((2, 3, 4), requires_grad=True)

Tensor 自动微分函数

torch.Tensor.grad

此属性默认为 None,并在第一次调用 backward() 计算 self 的梯度时变为 Tensor。

torch.Tensor.requires_grad

如果此 Tensor 需要计算梯度,则为 True,否则为 False

torch.Tensor.is_leaf

按照惯例,所有 requires_gradFalse 的 Tensor 都是叶节点 Tensor。

torch.Tensor.backward([gradient, ...])

计算当前张量相对于图叶节点的梯度。

torch.Tensor.detach

返回一个新 Tensor,与当前计算图分离。

torch.Tensor.detach_

将 Tensor 与创建它的计算图分离,使其成为叶节点。

torch.Tensor.register_hook(hook)

注册一个反向钩子。

torch.Tensor.register_post_accumulate_grad_hook(hook)

注册一个在梯度累积后运行的反向钩子。

torch.Tensor.retain_grad()

使此 Tensor 的 gradbackward() 期间被填充。

Function

torch.autograd.Function(*args, **kwargs)[source][source]

创建自定义 autograd.Function 的基类。

要创建自定义 autograd.Function,请从此类继承并实现 forward()backward() 静态方法。然后,要在前向传播中使用您的自定义算子,请调用类方法 apply。不要直接调用 forward()

为了确保正确性和最佳性能,请确保您调用了 ctx 上的正确方法,并使用 torch.autograd.gradcheck() 验证了您的反向函数。

有关如何使用此类的更多详细信息,请参阅扩展 torch.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
>>>
>>> # Use it by calling the apply method:
>>> output = Exp.apply(input)

Function.forward

定义自定义自动微分 Function 的前向计算。

Function.backward

定义使用反向模式自动微分进行操作求导的公式。

Function.jvp

定义使用前向模式自动微分进行操作求导的公式。

Function.vmap

定义此 autograd.Function 在 torch.vmap() 下的行为。

上下文方法混合

创建新的 Function 时,ctx 可使用以下方法。

function.FunctionCtx.mark_dirty

将给定的张量标记为在就地操作中已修改。

function.FunctionCtx.mark_non_differentiable

将输出标记为不可微分。

function.FunctionCtx.save_for_backward

保存给定的张量以供将来调用 backward()

function.FunctionCtx.set_materialize_grads

设置是否具体化梯度张量。

自定义 Function 工具类

用于 backward 方法的装饰器。

function.once_differentiable

用于构建 PyTorch 工具的基础自定义 Function

function.BackwardCFunction

此类用于内部自动微分工作。

function.InplaceFunction

此类仅为向后兼容而存在。

function.NestedIOFunction

此类仅为向后兼容而存在。

数值梯度检查

gradcheck

检查通过小有限差分计算的梯度与 inputs 中浮点或复数类型且设置了 requires_grad=True 的张量相对于它们的解析梯度是否一致。

gradgradcheck

检查通过小有限差分计算的梯度之梯度与 inputsgrad_outputs 中浮点或复数类型且设置了 requires_grad=True 的张量相对于它们的解析梯度是否一致。

GradcheckError

gradcheck()gradgradcheck() 引发的错误。

分析器

自动微分包含一个分析器,允许您检查模型中不同算子的成本 - 包括在 CPU 和 GPU 上。目前实现了三种模式:仅限 CPU 使用 profile;基于 nvprof(同时记录 CPU 和 GPU 活动)使用 emit_nvtx;以及基于 vtune 分析器使用 emit_itt

torch.autograd.profiler.profile(enabled=True, *, use_cuda=False, use_device=None, record_shapes=False, with_flops=False, profile_memory=False, with_stack=False, with_modules=False, use_kineto=False, use_cpu=True, experimental_config=None, acc_events=False, custom_trace_id_callback=None)[source][source]

管理自动微分分析器状态并保存结果摘要的上下文管理器。

在底层,它只是记录 C++ 中执行的函数事件,并将这些事件暴露给 Python。您可以将任何代码包装在其中,它将只报告 PyTorch 函数的运行时。注意:分析器是线程本地的,并自动传播到异步任务中。

参数
  • enabled (bool, 可选) – 将此设置为 False 会使此上下文管理器成为空操作。

  • use_cuda (bool, 可选) – 使用 cudaEvent API 同时启用 CUDA 事件的计时。(将被弃用)

  • use_device (str, 可选) – 启用设备事件的计时。使用 cuda 时,每张量操作会增加大约 4us 的开销。有效的设备选项是 ‘cuda’、‘xpu’、‘mtia’ 和 ‘privateuseone’。

  • record_shapes (bool, 可选) – 如果设置了形状记录,将收集关于输入维度的信息。这使得用户可以看到底层使用了哪些维度,并可以使用 prof.key_averages(group_by_input_shape=True) 进一步按维度分组。请注意,形状记录可能会扭曲您的分析数据。建议分别进行开启和关闭形状记录的运行来验证计时。对于最底层事件(在嵌套函数调用的情况下),扭曲很可能是微不足道的。但对于更高级别的函数,由于形状收集,总的自身 CPU 时间可能会人为增加。

  • with_flops (bool, 可选) – 如果设置了 with_flops,分析器将使用算子的输入形状估算 FLOPs(浮点运算)值。这使得用户可以估算硬件性能。目前,此选项仅适用于矩阵乘法和二维卷积算子。

  • profile_memory (bool, 可选) – 跟踪张量内存分配/释放。

  • with_stack (bool, 可选) – 记录算子的源信息(文件和行号)。

  • with_modules (bool) – 记录与算子调用栈对应的模块层次结构(包括函数名)。例如,如果模块 A 的 forward 调用了模块 B 的 forward,其中包含一个 aten::add 算子,则 aten::add 的模块层次结构是 A.B。注意,目前此支持仅适用于 TorchScript 模型而非即时模式模型。

  • use_kineto (bool, 可选) – 实验性功能,启用 Kineto 分析器进行性能分析。

  • use_cpu (bool, optional) – 分析 CPU 事件;设置为 False 需要 use_kineto=True,可用于降低纯 GPU 分析的开销。

  • experimental_config (_ExperimentalConfig) – 由 Kineto 等分析库使用的一组实验性选项。注意,不保证向后兼容性。

  • acc_events (bool) – 启用跨多个分析周期的 FunctionEvents 累积

示例

>>> x = torch.randn((1, 1), requires_grad=True)
>>> with torch.autograd.profiler.profile() as prof:
>>>     for _ in range(100):  # any normal python code, really!
>>>         y = x ** 2
>>>         y.backward()
>>> # NOTE: some columns were removed for brevity
>>> print(prof.key_averages().table(sort_by="self_cpu_time_total"))
-----------------------------------  ---------------  ---------------  ---------------
Name                                 Self CPU total   CPU time avg     Number of Calls
-----------------------------------  ---------------  ---------------  ---------------
mul                                  32.048ms         32.048ms         200
pow                                  27.041ms         27.041ms         200
PowBackward0                         9.727ms          55.483ms         100
torch::autograd::AccumulateGrad      9.148ms          9.148ms          100
torch::autograd::GraphRoot           691.816us        691.816us        100
-----------------------------------  ---------------  ---------------  ---------------

profiler.profile.export_chrome_trace

将 EventList 导出为 Chrome 追踪工具文件。

profiler.profile.key_averages

按键对所有函数事件求平均。

profiler.profile.self_cpu_time_total

返回在 CPU 上花费的总时间。

profiler.profile.total_average

对所有事件求平均。

profiler.parse_nvprof_trace

profiler.EnforceUnique

如果一个键出现多次则抛出错误。

profiler.KinetoStepTracker

提供了一个抽象,用于全局增加步数计数。

profiler.record_function

上下文管理器/函数装饰器,在运行 autograd 分析器时为代码块/函数添加标签。

profiler_util.Interval

profiler_util.Kernel

profiler_util.MemRecordsAcc

用于在间隔内访问 mem_records 的加速结构。

profiler_util.StringTable

class torch.autograd.profiler.emit_nvtx(enabled=True, record_shapes=False)[source][source]

上下文管理器,使每个 autograd 操作发出一个 NVTX 范围。

在 nvprof 下运行程序时非常有用

nvprof --profile-from-start off -o trace_name.prof -- <regular command here>

遗憾的是,无法强制 nvprof 将其收集的数据刷新到磁盘,因此对于 CUDA 分析,必须使用此上下文管理器来标注 nvprof 追踪,并在进程退出后才能检查它们。然后,可以使用 NVIDIA Visual Profiler (nvvp) 来可视化时间线,或者 torch.autograd.profiler.load_nvprof() 可以加载结果以供检查,例如在 Python REPL 中。

参数
  • enabled (bool, optional) – 设置 enabled=False 会使此上下文管理器成为一个无操作(no-op)。默认值: True

  • record_shapes (bool, optional) – 如果 record_shapes=True,包裹每个 autograd 操作的 nvtx 范围将附加关于该操作接收到的 Tensor 参数尺寸的信息,格式如下: [[arg0.size(0), arg0.size(1), ...], [arg1.size(0), arg1.size(1), ...], ...] 非 Tensor 参数将用 [] 表示。参数将按照后端操作接收它们的顺序进行列表。请注意,此顺序可能与这些参数在 Python 端传递的顺序不匹配。另请注意,形状记录可能会增加 nvtx 范围创建的开销。默认值: False

示例

>>> with torch.cuda.profiler.profile():
...     model(x)  # Warmup CUDA memory allocator and profiler
...     with torch.autograd.profiler.emit_nvtx():
...         model(x)

前向-后向关联

在 Nvidia Visual Profiler 中查看使用 emit_nvtx 创建的分析结果时,将每个后向传播操作与相应的前向传播操作关联起来可能会很困难。为了简化这项任务,emit_nvtx 会将序列号信息附加到其生成的范围内。

在前向传播过程中,每个函数范围都用 seq=<N> 进行了标注。seq 是一个运行计数器,每次创建一个新的后向 Function 对象并为其后向传播而存储时递增。因此,与每个前向函数范围关联的 seq=<N> 标注告诉您,如果此函数创建了一个后向 Function 对象,则该后向对象将接收序列号 N。在后向传播过程中,包裹每个 C++ 后向 Function 的 apply() 调用的顶层范围用 stashed seq=<M> 进行了标注。M 是创建后向对象时使用的序列号。通过比较后向传播中的 stashed seq 数字与前向传播中的 seq 数字,您可以追踪到哪个前向操作创建了哪个后向 Function。

在后向传播期间执行的任何函数也用 seq=<N> 进行了标注。在默认后向传播(`create_graph=False` 时)期间,此信息不相关,实际上,对于所有此类函数,N 可能只是 0。只有与后向 Function 对象的 apply() 方法关联的顶层范围有用,作为将这些 Function 对象与之前的正向传播关联起来的一种方式。

二阶后向传播

另一方面,如果正在进行一个 `create_graph=True` 的后向传播(换句话说,如果您正在准备进行二阶后向传播),后向传播期间每个函数的执行都会被赋予一个非零且有用的 seq=<N>。这些函数本身可能会创建 Function 对象,以便稍后在二阶后向传播期间执行,就像前向传播中的原始函数所做的那样。后向传播和二阶后向传播之间的关系在概念上与前向传播和后向传播之间的关系是相同的:这些函数仍然发出带有当前序列号标记的范围,它们创建的 Function 对象仍然存储这些序列号,并且在最终的二阶后向传播期间,Function 对象的 apply() 范围仍然用 stashed seq 数字进行标记,这些数字可以与后向传播中的 `seq` 数字进行比较。

class torch.autograd.profiler.emit_itt(enabled=True, record_shapes=False)[source][source]

上下文管理器,使每个 autograd 操作发出一个 ITT 范围。

在 Intel(R) VTune Profiler 下运行程序时非常有用

vtune <--vtune-flags> <regular command here>

Instrumentation and Tracing Technology (ITT) API 使您的应用程序能够在执行期间跨不同的 Intel 工具生成和控制追踪数据的收集。此上下文管理器用于标注 Intel(R) VTune Profiling 追踪。借助此上下文管理器,您将能够在 Intel(R) VTune Profiler GUI 中看到带标签的范围。

参数
  • enabled (bool, optional) – 设置 enabled=False 会使此上下文管理器成为一个无操作(no-op)。默认值: True

  • record_shapes (bool, optional) – 如果 record_shapes=True,包裹每个 autograd 操作的 itt 范围将附加关于该操作接收到的 Tensor 参数尺寸的信息,格式如下: [[arg0.size(0), arg0.size(1), ...], [arg1.size(0), arg1.size(1), ...], ...] 非 Tensor 参数将用 [] 表示。参数将按照后端操作接收它们的顺序进行列表。请注意,此顺序可能与这些参数在 Python 端传递的顺序不匹配。另请注意,形状记录可能会增加 itt 范围创建的开销。默认值: False

示例

>>> with torch.autograd.profiler.emit_itt():
...     model(x)

profiler.load_nvprof

打开 nvprof 追踪文件并解析 autograd 标注。

调试和异常检测

class torch.autograd.detect_anomaly(check_nan=True)[source][source]

启用 autograd 引擎异常检测的上下文管理器。

这做了两件事

  • 在启用检测的情况下运行前向传播将允许后向传播打印创建失败后向函数的前向操作的追溯信息。

  • 如果 check_nanTrue,任何生成“nan”(非数字)值的后向计算将抛出错误。默认值 True

警告

此模式应仅用于调试,因为不同的测试会减慢程序执行速度。

示例

>>> import torch
>>> from torch import autograd
>>> class MyFunc(autograd.Function):
...     @staticmethod
...     def forward(ctx, inp):
...         return inp.clone()
...     @staticmethod
...     def backward(ctx, gO):
...         # Error during the backward pass
...         raise RuntimeError("Some error in backward")
...         return gO.clone()
>>> def run_fn(a):
...     out = MyFunc.apply(a)
...     return out.sum()
>>> inp = torch.rand(10, 10, requires_grad=True)
>>> out = run_fn(inp)
>>> out.backward()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/your/pytorch/install/torch/_tensor.py", line 93, in backward
        torch.autograd.backward(self, gradient, retain_graph, create_graph)
      File "/your/pytorch/install/torch/autograd/__init__.py", line 90, in backward
        allow_unreachable=True)  # allow_unreachable flag
      File "/your/pytorch/install/torch/autograd/function.py", line 76, in apply
        return self._forward_cls.backward(self, *args)
      File "<stdin>", line 8, in backward
    RuntimeError: Some error in backward
>>> with autograd.detect_anomaly():
...     inp = torch.rand(10, 10, requires_grad=True)
...     out = run_fn(inp)
...     out.backward()
    Traceback of forward call that caused the error:
      File "tmp.py", line 53, in <module>
        out = run_fn(inp)
      File "tmp.py", line 44, in run_fn
        out = MyFunc.apply(a)
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
      File "/your/pytorch/install/torch/_tensor.py", line 93, in backward
        torch.autograd.backward(self, gradient, retain_graph, create_graph)
      File "/your/pytorch/install/torch/autograd/__init__.py", line 90, in backward
        allow_unreachable=True)  # allow_unreachable flag
      File "/your/pytorch/install/torch/autograd/function.py", line 76, in apply
        return self._forward_cls.backward(self, *args)
      File "<stdin>", line 8, in backward
    RuntimeError: Some error in backward
class torch.autograd.set_detect_anomaly(mode, check_nan=True)[source][source]

上下文管理器,用于开启或关闭 autograd 引擎的异常检测。

set_detect_anomaly 将根据其参数 mode 启用或禁用 autograd 异常检测。它可以作为上下文管理器或函数使用。

有关异常检测行为的详细信息,请参阅上文的 detect_anomaly

参数
  • mode (bool) – 标志,是否启用异常检测(True`),或禁用(False)。

  • check_nan (bool) – 标志,是否在后向传播产生“nan”(非数字)时抛出错误

grad_mode.set_multithreading_enabled

上下文管理器,用于开启或关闭多线程后向传播。

Autograd 计算图

Autograd 提供了一些方法,允许检查计算图并在后向传播期间介入行为。

一个 torch.Tensorgrad_fn 属性持有一个 torch.autograd.graph.Node,如果该 tensor 是一个被 autograd 记录的操作的输出(即,autograd 模式已启用并且至少有一个输入需要梯度),否则为 None

graph.Node.name

返回名称。

graph.Node.metadata

返回元数据。

graph.Node.next_functions

graph.Node.register_hook

注册一个后向钩子。

graph.Node.register_prehook

注册一个后向预钩子。

graph.increment_version

更新 autograd 元数据跟踪,跟踪给定的 Tensor 是否进行了原地修改。

一些操作需要在前向传播期间保存中间结果,以便执行后向传播。这些中间结果被保存为 grad_fn 上的属性,并且可以访问。例如

>>> a = torch.tensor([0., 0., 0.], requires_grad=True)
>>> b = a.exp()
>>> print(isinstance(b.grad_fn, torch.autograd.graph.Node))
True
>>> print(dir(b.grad_fn))
['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_raw_saved_result', '_register_hook_dict', '_saved_result', 'metadata', 'name', 'next_functions', 'register_hook', 'register_prehook', 'requires_grad']
>>> print(torch.allclose(b.grad_fn._saved_result, b))
True

您还可以使用钩子定义这些保存的 tensor 如何打包/解包。一个常见的应用是牺牲计算来换取内存,方法是将这些中间结果保存到磁盘或 CPU,而不是将其留在 GPU 上。如果您的模型在评估期间适合 GPU,但在训练期间不适合,这尤其有用。另请参阅 保存的 tensor 的钩子

class torch.autograd.graph.saved_tensors_hooks(pack_hook, unpack_hook)[source][source]

上下文管理器,用于设置保存的 tensor 的一对打包/解包钩子。

使用此上下文管理器,定义一个操作的中间结果在保存前应如何打包,并在检索时如何解包。

在此上下文中,`pack_hook` 函数将在每次一个操作为后向传播保存一个 tensor 时被调用(这包括使用 save_for_backward() 保存的中间结果,以及由 PyTorch 定义的操作记录的结果)。然后,`pack_hook` 的输出被存储在计算图中,而不是原始 tensor。

当保存的 tensor 需要被访问时,即在执行 torch.Tensor.backward()torch.autograd.grad() 时,`unpack_hook` 被调用。它以 `pack_hook` 返回的*打包*对象作为参数,并应返回一个 tensor,其内容与原始 tensor 相同(作为输入传递给相应的 `pack_hook`)。

这些钩子应具有以下签名

pack_hook(tensor: Tensor) -> Any

unpack_hook(Any) -> Tensor

其中 `pack_hook` 的返回值是 `unpack_hook` 的有效输入。

通常,您希望 `unpack_hook(pack_hook(t))` 在值、尺寸、数据类型和设备方面等于 `t`。

示例

>>> def pack_hook(x):
...     print("Packing", x)
...     return x
>>>
>>> def unpack_hook(x):
...     print("Unpacking", x)
...     return x
>>>
>>> a = torch.ones(5, requires_grad=True)
>>> b = torch.ones(5, requires_grad=True) * 2
>>> with torch.autograd.graph.saved_tensors_hooks(pack_hook, unpack_hook):
...     y = a * b
Packing tensor([1., 1., 1., 1., 1.], requires_grad=True)
Packing tensor([2., 2., 2., 2., 2.], grad_fn=<MulBackward0>)
>>> y.sum().backward()
Unpacking tensor([1., 1., 1., 1., 1.], requires_grad=True)
Unpacking tensor([2., 2., 2., 2., 2.], grad_fn=<MulBackward0>)

警告

在任意一个钩子的输入上执行原地操作可能会导致未定义的行为。

警告

一次只允许一对钩子。当递归嵌套此上下文管理器时,只有最内层的钩子对会被应用。

class torch.autograd.graph.save_on_cpu(pin_memory=False, device_type='cuda')[source][source]

上下文管理器,在此管理器下,前向传播保存的 tensor 将存储在 CPU 上,然后为后向传播进行检索。

在此上下文管理器中执行操作时,在前向传播期间保存在计算图中的中间结果将被移动到 CPU,然后在后向传播需要时复制回原始设备。如果计算图已经在 CPU 上,则不执行 tensor 复制。

使用此上下文管理器,用计算换取 GPU 内存使用(例如,当您的模型在训练期间不适合 GPU 内存时)。

参数

pin_memory (bool) – 如果 True,tensor 将在打包期间保存到 CPU 锁页内存(pinned memory),并在解包期间异步复制到 GPU。默认值为 False。另请参阅 使用锁页内存缓冲区

示例

>>> a = torch.randn(5, requires_grad=True, device="cuda")
>>> b = torch.randn(5, requires_grad=True, device="cuda")
>>> c = torch.randn(5, requires_grad=True, device="cuda")
>>>
>>> def f(a, b, c):
...     prod_1 = a * b           # a and b are saved on GPU
...     with torch.autograd.graph.save_on_cpu():
...         prod_2 = prod_1 * c  # prod_1 and c are saved on CPU
...     y = prod_2 * a           # prod_2 and a are saved on GPU
...     return y
>>>
>>> y = f(a, b, c)
>>> del a, b, c  # for illustration only
>>> # the content of a, b, and prod_2 are still alive on GPU
>>> # the content of prod_1 and c only live on CPU
>>> y.sum().backward()  # all CPU tensors are moved back to GPU, for backward
>>> # all intermediary tensors are released (deleted) after the call to backward
class torch.autograd.graph.disable_saved_tensors_hooks(error_message)[source][source]

上下文管理器,禁用保存的 tensor 默认钩子功能。

当您正在创建一个功能,但该功能与保存的 tensor 默认钩子不兼容时很有用。

参数

error_message (str) – 当保存的 tensor 默认钩子已被禁用但仍被使用时,将抛出一个带有此错误消息的 RuntimeError。

返回类型

Generator[None, None, None]

示例

>>> message = "saved tensors default hooks are disabled"
>>> with torch.autograd.graph.disable_saved_tensors_hooks(message):
...     # Raises RuntimeError: saved tensors default hooks are disabled
...     with torch.autograd.graph.save_on_cpu():
...         pass
class torch.autograd.graph.register_multi_grad_hook(tensors, fn, *, mode='all')[source][source]

注册一个多梯度后向钩子。

支持两种模式:"all""any"

"all" 模式下,在计算完关于 tensors 中每个 tensor 的梯度后将调用该钩子。如果一个 tensor 在 tensors 中但不属于计算图的一部分,或者如果对于当前 .backward().grad() 调用指定的任何 inputs 不需要一个 tensor 来计算梯度,这个 tensor 将被忽略,并且钩子不会等待其梯度被计算。

在计算完所有非忽略 tensor 的梯度后,将使用这些梯度调用 fn。对于未计算其梯度的 tensor 将传递 None

"any" 模式下,在计算完关于 tensors 中某个 tensor 的第一个梯度后将调用钩子。将使用该梯度作为参数调用钩子。

钩子不应修改其参数。

此函数返回一个带有方法 handle.remove() 的句柄,用于移除钩子。

注意

有关此钩子何时执行以及其执行相对于其他钩子的顺序的更多信息,请参阅 后向钩子执行

示例

>>> import torch
>>>
>>> a = torch.rand(2, 3, requires_grad=True)
>>> b = torch.rand(2, 3, requires_grad=True)
>>> c = a * b
>>> d = a * b
>>>
>>> def fn(grads):
...     print([g is not None for g in grads])
...
>>> torch.autograd.graph.register_multi_grad_hook((a, b, c, d), fn)
>>>
>>> c.sum().backward(retain_graph=True)
[True, True, True, False]
>>> c.sum().backward(inputs=(a,), retain_graph=True)
[True, False, True, False]
>>>
返回类型

RemovableHandle

class torch.autograd.graph.allow_mutation_on_saved_tensors[source][source]

上下文管理器,在此管理器下允许修改为后向传播保存的 tensor。

在此上下文管理器下,为后向传播保存的 tensor 在修改时会被克隆,因此原始版本在后向传播期间仍然可以使用。通常,修改为后向传播保存的 tensor 将导致在后向传播期间使用它时抛出错误。

为了确保正确的行为,前向和后向传播都应在相同的上下文管理器下运行。

返回

一个 _AllowMutationOnSavedContext 对象,存储此上下文管理器管理的状态。此对象可用于调试目的。上下文管理器管理的状态在退出时自动清除。

返回类型

Generator[_AllowMutationOnSavedContext, None, None]

示例

>>> import torch
>>> with torch.autograd.graph.allow_mutation_on_saved_tensors():
...     # forward
...     a = torch.ones(2, 3, requires_grad=True)
...     b = a.clone()
...     out = (b**2).sum()
...     b.sin_()
...     # backward
...     out.sum().backward()
...
tensor([[0.8415, 0.8415, 0.8415],
        [0.8415, 0.8415, 0.8415]], grad_fn=<SinBackward0>)
class torch.autograd.graph.GradientEdge(node, output_nr)[source][source]

表示 autograd 计算图中给定梯度边的对象。

要获取将计算给定 Tensor 梯度的梯度边,您可以执行 edge = autograd.graph.get_gradient_edge(tensor)

torch.autograd.graph.get_gradient_edge(tensor)[source][source]

获取用于计算给定 Tensor 梯度的梯度边。

特别是,调用 g = autograd.grad(loss, input)g = autograd.grad(loss, get_gradient_edge(input)) 是等价的。

返回类型

GradientEdge

文档

访问 PyTorch 全面的开发者文档

查看文档

教程

获取适用于初学者和高级开发者的深入教程

查看教程

资源

查找开发资源并获得问题解答

查看资源