Automatic differentiation package - torch.autograd

译者:@ZhenLei Xu

校对者:@青梅往事

torch.autograd 提供了类和函数用来对任意标量函数进行求导.只需要对已有的代码进行微小的改变-只需要将所有的 tensors 包含在 Variable 对象中即可.

torch.autograd.backward(variables, grad_variables=None, retain_graph=None, create_graph=None, retain_variables=None)

给定图某一个的节点变量variables,计算对该变量求导的梯度和.

计算图可以通过链式法则求导.如果任何 variables 都是非标量(比如 他们的 data 属性中有多个元素)并且需要求导, 那么此函数需要指定 grad_variables. 它的长度应该和variables的长度匹配,里面保存了相关 variable 的梯度 (对于不需要 gradient tensor 的 variable, 应制定为 None).

此函数累积叶子节点 variables 计算的梯度 - 调用此函数之前应先将叶子节点 variables 梯度置零.

参数:

  • variables (Variable 列表): 被求微分的叶子节点.
  • grad_variables ((Tensor, Variable 或 None) 列表):对应 variable 的梯度. 任何张量将自动转换为变量除非create_graphTrue. 没有值可以被指定为标量变量或者不需要被求导. 如果没有值被所有的grad_variables接受, 那么该参数是可以被省略的.
  • retain_graph (bool, 可选): 如果是 False, 该图计算过的梯度被释放掉.注意的是,几乎所有情况都设置为True并不是必须的并且能够高效的计算.将该 create_graph 参数值设置为默认即可.
  • create_graph (bool, 可选): 如果是 True, 将会建立一个梯度图, 用来求解高阶导数.默认为 False, 除非 grad_variables 拥有不止一个 易变的 Variable.
torch.autograd.grad(outputs, inputs, grad_outputs=None, retain_graph=None, create_graph=None, only_inputs=True, allow_unused=False)

计算并返回给定值的梯度的和.

grad_outputs 是一个列表同时长度与 output 一样, 存放了预先计算 input 的梯度的和. 如果 output 不需要被求导, 那么梯度将为 None). 当不需要派生图时,可以将梯度作为张量,或者作为变量,在这种情况下,图将被创建.

如果参数 only_inputsTrue, 该方法将会返回给定输入的梯度值列表.如果为 False, 那么遗留下来的所有叶子节点的梯度都会被计算, 被且会被列加到 .grad 参数中.

参数:

  • outputs (变量序列): 梯度函数的返回值.
  • inputs (变量序列): 需要计算的梯度的输入 (并且不会被累加到 .grad 参数中).
  • grad_outputs (张量或变量序列): 每一个输出的梯度. 所有的张量都会变成变量并且是可变的除非参数 create_graphTrue. 没有值可以被指定为标量变量或者不需要变化的值. 如果所有 grad_variabls 都可以接受 None 值,那么这个参数是可选的.
  • retain_graph (bool, 可选): 如果是 False, 用于计算 grad 的图将被释放. 几乎所有情况都设置为True 并不是必须的并且能够高效地运行. 默认与 create_graph 参数一样.
  • create_graph (bool, 可选): 如果是 True, 梯度图将会被建立,用来求解高阶导数. 默认为 False , 除非参数 grad_variables 包含不只一个变量.
  • only_inputs (bool, 可选): 如果是 True, 叶子节点的导数将会在图中, 但是不会出现在参数 inputs 也不会被计算以及累加. 默认为 True.
  • allow_unused (bool, 可选): 如果是 False, 指定计算输出时未使用的输入(因此它们的 grad 始终为零)是错误的. 默认为 False.

Variable (变量)

API compatibility

Variable API 几乎与常规 Tensor API 相同(一些会覆盖梯度计算输入的内置方法除外). 在大多数情况下, 变量量可以安全地替换张量并且代码将保持正常工作. 因为这个, 我们没有记录变量上的所有操作, 你应该参阅 torch.Tensor 文档来查看变量上的所有操作.

In-place operations on Variables

在 autograd 支持就地操作是一件困难的事情, 在大多数情况下我们不鼓励使用. Autograd 积极的缓冲区释放和重用使得它非常高效, 而且很少有就地操作实际上大量地降低了内存使用量的情况. 除非你正在大量的的内存压力下运行, 否则你可能永远不需要使用它们.

In-place correctness checks

所有的 Variable 跟踪适用于它们的就地操作, 并且如果实现检测到一个变量是否被其中一个函数后台保存, 但是之后它被就地修改了, 会在开始求导时会报出异常. 这确保了如果你在就地使用函数并没有看到任何错误, 你可以肯定的是计算变量是正确的.

class torch.autograd.Variable

封装一个张量用来各种操作.

变量是张量对象周围的轻包装,能够拥有导数等数据, 这个引用允许回溯整个操作链创建数据. 如果变量已经由用户创建, 它的 grad_fn 为 None 我们称之为叶子节点.

由于 autograd 只支持标量值函数微分, grad 大小始终与数据大小匹配. 此外,导数通常只分配 叶变量,否则将始终为零.

参数:

  • data: 包裹任何类型的张量.
  • grad: 变量保持类型和位置匹配的变量 .data. 这个属性是懒惰的分配,不能被重新分配.
  • requires_grad: 指示变量是否已被使用的布尔值由包含任何变量的子图创建,需要它. 有关更多详细信息,请参阅 excluded-subgraphs.只能在叶变量上进行更改.
  • volatile: 布尔值表示应该使用变量推理模式,即不保存历史. 查看 反向排除 subgraphs (子图) 更多细节. 只能在叶变量上进行更改.
  • is_leaf: 指示是否为叶子节点,即是否由用户创建的节点.
  • grad_fn: 导数函数跟踪.

参数:

  • data (任何 tensor 类): 用来包装的张量.
  • requires_grad (bool): 指示是否要被求导. 仅限关键字.
  • volatile (bool): 指示是否可变. 仅限关键字.
backward(gradient=None, retain_graph=None, create_graph=None, retain_variables=None)

给定图叶子节点计算导数.

该图使用链式规则进行计算. 如果变量是非标量(即其数据具有多个元素)并且需要 改变,该功能另外需要指定“梯度”.它应该是一个包含匹配类型和位置的张量 微分函数的梯度w.r.t. self .

这个功能在叶子上累积梯度 - 你可能需要调用之前将它们置零.

参数:

  • gradient (Tensor, Variable or None): 计算变量的梯度. 如果是张量,则会自动转换到一个变量,这是挥发性的,除非 create_graph 为真.没有值可以被指定为标量变量或那些 不要求毕业. 如果一个None值是可以接受的这个参数是可选的.

  • retain_graph (bool, 可选): 如果 “False” ,则用于计算的图形导数将被释放. 请注意,在几乎所有情况下设置这个选项为 True 是不需要的,通常可以解决在一个更有效的方式. 默认值为create_graph.

  • create_graph (bool, 可选): 如果“真”,派生图将会被构造,允许计算更高阶的导数. 默认为 False,除非 gradient 是一个volatile变量.

detach()

将一个Variable从创建它的图中分离,并把它设置成 leaf variable.

返回变量使用与原始数据张量相同的数据张量,其中任何一个的就地修改都将被看到,并可能触发 错误在正确性检查.

detach_()

将一个 Variable 从创建它的图中分离,并把它设置成 leaf variable.

register_hook(hook)

注册一个backward钩子.

每次gradients被计算的时候,这个 hook 都被调用 .hook 应该拥有以下签名:

hook(grad) -> Variable or None

hook不应该修改它的输入,但是它可以选择性的返回一个替代当前梯度的新梯度.

这个函数返回一个 句柄 (handle).它有一个方法 handle.remove(),可以用这个方法将 hook 从 module 移除.

示例:

>>> v = Variable(torch.Tensor([0, 0, 0]), requires_grad=True)
>>> h = v.register_hook(lambda grad: grad * 2)  # double the gradient
>>> v.backward(torch.Tensor([1, 1, 1]))
>>> v.grad.data
 2
 2
 2
[torch.FloatTensor of size 3]
>>> h.remove()  # removes the hook
retain_grad()

为非叶变量启用 .grad 属性.

Function (函数)

class torch.autograd.Function

记录操作历史记录并定义区分操作的方法.

每个执行在 Varaibles 上的 operation 都会创建一个 Function 对象,这个 Function 对象执行计算工作,同时记录下来.这个历史以有向无环图的形式保存下来, 有向图的节点为 functions ,有向图的边代表数据依赖关系 (input<-output).之后,当 backward 被调用的时候,计算图以拓扑顺序处理,通过调用每个 Function 对象的 backward(), 同时将返回的梯度传递给下一个 Function.

通常情况下,用户能和 Functions 交互的唯一方法就是创建 Function 的子类,定义新的 operation. 这是扩展 torch.autograd 的推荐方法.

每个 Function 只被使用一次(在forward过程中).

参数: requires_grad: 布尔类型依赖于方法 backward() 会不会还会被使用.

比如:

>>> 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_variables
>>>         return grad_output * result

static backward(ctx, *grad_outputs)[source]

定义反向传播操作

这个方法将会被继承他的所有子类覆盖.

第一个参数为上下文参数, 接下来可以输入任何张量或变量 (张量或其他类型), 并且有多个返回值, 并且为函数 forward() 的输入. 每个参数都是给定输出的导数, 并且每一个输出都是输入的导数.

上下文可以用来检索转发过程中保存的变量.

static forward(ctx, *args, **kwargs)

进行操作.

这个方法将会被继承他的所有子类覆盖.

第一个参数为上下文参数,接下来可以输入任何张量或变量 (张量或其他类型).

上下文可以用来存储可以在回传期间检索的变量.

Profiler(分析器)

Autograd 包含一个分析器, 可以让你检查你的模型在CPU 和 GPU 上不同运算的成本. 目前实现有两种模式 - 只使用 CPU 的 profile. 和基于 nvprof (注册 CPU 和 GPU 活动) 的方式使用 emit_nvtx.

class torch.autograd.profiler.profile(enabled=True)

结果的评价指标.

参数:enabled (bool, 可选) – 如果设置为 False ,则没有评价指标. Default: True.

示例:

>>> x = Variable(torch.randn(1, 1), requires_grad=True)
>>> with torch.autograd.profiler.profile() as prof:
...     y = x ** 2
...     y.backward()
>>> # NOTE: some columns were removed for brevity
... print(prof)
-------------------------------------  ---------------  ---------------
Name                                          CPU time        CUDA time
-------------------------------------  ---------------  ---------------
PowConstant                                  142.036us          0.000us
N5torch8autograd9GraphRootE                   63.524us          0.000us
PowConstantBackward                          184.228us          0.000us
MulConstant                                   50.288us          0.000us
PowConstant                                   28.439us          0.000us
Mul                                           20.154us          0.000us
N5torch8autograd14AccumulateGradE             13.790us          0.000us
N5torch8autograd5CloneE                        4.088us          0.000us
export_chrome_trace(path)

将EventList导出为Chrome跟踪工具文件.

断点能够通过 chrome://tracing URL来读取.

参数:path (str) – 制定断点写的路径.

key_averages()

平均所有的功能指标通过他们的键.

返回值:包含 FunctionEventAvg 对象的 EventList.

table(sort_by=None)

打印操作表

参数:sort_by (str, 可选) – 用来对参数进行排序. 默认情况下,它们以与登记相同的顺序打印. 有效的键: cpu_time, cuda_time, cpu_time_total, cuda_time_total, count.

返回值:包含表的字符串.

total_average()

所有事件的平均指标.

返回值:一个 FunctionEventAvg 对象.

class torch.autograd.profiler.emit_nvtx(enabled=True)

使每个autograd操作都发出一个NVTX范围的上下文管理器.

如下使用是正确的:

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

不幸的是,没有办法强制nvprof刷新收集到的数据到磁盘,因此对于 CUDA 分析,必须使用此上下文管理器进行注释 nvprof 跟踪并等待进程在检查之前退出. 然后,可以使用NVIDIA Visual Profiler(nvvp)来显示时间轴,或者 torch.autograd.profiler.load_nvprof() 可以加载检查结果.

参数:enabled (bool, 可选) – 如果设置为 False ,则没有评价指标. 默认: True.

示例:

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

打开 nvprof trace 文件.

参数:path (str) – nvprof trace 文件路径.

results matching ""

    No results matching ""