使用 autograd 计算输出相对于输入的雅可比矩阵

Using autograd to compute Jacobian matrix of outputs with respect to inputs

如果这个问题很明显或微不足道,我深表歉意。我对 pytorch 很陌生,我想了解 pytorch 中的 autograd.grad 函数。我有一个神经网络 G,它接受输入 (x,t) 和输出 (u,v)。这是 G 的代码:

class GeneratorNet(torch.nn.Module):
    """
    A three hidden-layer generative neural network
    """

    def __init__(self):
        super(GeneratorNet, self).__init__()
        self.hidden0 = nn.Sequential(
            nn.Linear(2, 100),
            nn.LeakyReLU(0.2)
            )

        self.hidden1 = nn.Sequential(
            nn.Linear(100, 100),
            nn.LeakyReLU(0.2)
            )

        self.hidden2 = nn.Sequential(
            nn.Linear(100, 100),
            nn.LeakyReLU(0.2)
            )

        self.out = nn.Sequential(
            nn.Linear(100, 2),
            nn.Tanh()
            )

    def forward(self, x):
        x = self.hidden0(x)
        x = self.hidden1(x)
        x = self.hidden2(x)
        x = self.out(x)
        return x

或者简单地 G(x,t) = (u(x,t), v(x,t)) 其中 u(x,t) 和 v(x,t) 是标量值。目标:计算 $\frac{\partial u(x,t)}{\partial x}$ 和 $\frac{\partial u(x,t)}{\partial t}$。在每个训练步骤中,我都有一个大小为 $100$ 的小批量,所以 u(x,t) 是一个 [100,1] 张量。这是我计算偏导数的尝试,其中坐标是输入 (x,t),就像下面一样,我也向坐标添加了 requires_grad_(True) 标志:

tensor = GeneratorNet(coords)
tensor.requires_grad_(True)
u, v = torch.split(tensor, 1, dim=1)
du = autograd.grad(u, coords, grad_outputs=torch.ones_like(u), create_graph=True, 
                   retain_graph=True, only_inputs=True, allow_unused=True)[0]

du 现在是 [100,2] 张量。 问题:这是minibatch的100个输入点的偏张量吗?

还有类似的问题,例如计算输出相对于输入的导数,但我无法真正弄清楚发生了什么。如果这已经回答或微不足道,我再次道歉。非常感谢。

您发布的代码应该为您提供第一个输出的偏导数 w.r.t。输入。但是,您还必须在输入上设置 requires_grad_(True),否则 PyTorch 不会从输入开始构建计算图,因此它无法为它们计算梯度。

此版本的代码示例计算 dudv:

net = GeneratorNet()
coords = torch.randn(10, 2)
coords.requires_grad = True
tensor = net(coords)
u, v = torch.split(tensor, 1, dim=1)
du = torch.autograd.grad(u, coords, grad_outputs=torch.ones_like(u))[0]
dv = torch.autograd.grad(v, coords, grad_outputs=torch.ones_like(v))[0]

您还可以计算单个输出的偏导数:

net = GeneratorNet()
coords = torch.randn(10, 2)
coords.requires_grad = True
tensor = net(coords)
u, v = torch.split(tensor, 1, dim=1)
du_0 = torch.autograd.grad(u[0], coords)[0]

其中 du_0 == du[0].