megengine.autodiff.GradManager

class GradManager[源代码]

GradManager 负责计算梯度,或更一般地,矢量-雅可比积,通过反向模式做自动微分(又称为反向传播)。

反向模式自动微分为了最佳计算效率通常会重用许多中间张量。然而在交互式(REPL)环境中,很难知道用户之后将如何使用梯度从而预先保存某些张量。要解决此问题,用户必须以某种方式事先声明什么梯度需要被保留。在 GradManager 中,用户如果希望后续计算张量的梯度,则需要在该张量上调用 attach 方法。此外,在张量被 attach 之前对张量的任何计算都会从 autodiff 的角度完全被忽略,所以 attach 必须在需要微分的任何计算之前被调用。

例如,下面的自动微分代码

x = get_x()
y = f(x)
dy = ones_like(y)
dx = vjp(y, x, dy) # vector-Jacobian product

可用 GradManager 在交互式环境下重写为

with GradManager() as gm:
    x = get_x()
    gm.attach(x) # must be placed before any computation on x that needs differentiation
    y = f(x)
    dy = ones_like(y)
    gm.backward(y, dy) # doesn't need x, already known via attach()
    dx = x.grad # backward() saves result to .grad attribute

训练神经网络的一个更现实的例子是

gm = GradManager()
gm.attach(model.parameters())

for data in dataset:
    with gm:
        loss = model(data)
        gm.backward(loss)
    # gradients w.r.t. parameters is accumulated into their .grad attributes

你也可以使用 record()release() 而不使用 with 语义:

gm = GradManager()
gm.attach(model.parameters())

for data in dataset:
    gm.record()
    loss = model(data)
    gm.backward(loss)
    # backward() will clear recorded history and free resources
    # call release() if backward() is not called
    # gm.release()

为方便起见,可以(并非必须)重用 GradManager 。如在这些示例中,您只需要 attach 一个张量一次,而 GradManager 将永远记住它。但是,一个 GradManager 只能记录一次计算历史。要同时进行多种微分或进行高阶微分,可根据需要创建尽可能多的 GradManager。

注解

可变张量在执行符号微分时引入歧义:我们指的是 Tensor 的哪个版本?对于 attched 的张量,GradManager 通过在第一次遇见张量时 ‘snapshoting’ 它们来解决这种歧义,要么通过 record 之前就被 attach,要么通过 attach 如果 GradManager 已经在记录。attched 的张量将会被解释为它们的快照版本以进行区分。对 backward 的第一个参数的相同歧义是只需使用最新版本即可解决。

通常,在数据并行的时候,我们需要跨进程计算梯度的均值。使用者最终可获得平均的梯度若一个 “AllReduce” 回调函数像下面一样被注册的话:

import megengine.distributed as dist

gm = GradManager()
gm.attach(model.parameters(), callback=dist.make_allreduce_cb("MEAN"))

方法

attach(tensors[, callbacks])

指示 GradManager 跟踪张量上的操作,以便那些张量上的梯度,可以在之后进行计算。

attached_tensors()

Return attached tensor list from attach.

backward([y, dy])

对所有 attached Tensor 计算梯度 (或向量-雅可比积),并将其积累到对应 Tensor 的 .grad 属性中,在过程中释放资源。

record()

开始记录操作

release()

停止记录操作并释放为计算梯度而保留的资源