grad_outputs 在 torch.autograd.grad 中(交叉熵损失)

grad_outputs in torch.autograd.grad (CrossEntropyLoss)

我正在尝试 d(loss)/d(input)。我知道我有两个选择。

第一个选项:

    loss.backward()
    dlossdx = x.grad.data

第二个选项:

    # criterion = nn.CrossEntropyLoss(reduce=False)
    # loss = criterion(y_hat, labels)     
    # No need to call backward. 
    dlossdx = torch.autograd.grad(outputs = loss,
                                  inputs = x,
                                  grad_outputs = ? )

我的问题是:如果我使用交叉熵损失,我应该在第二个选项中传递什么作为grad_outputs

我放d(CE)/d(y_hat)吗?由于 pytorch crossentropy 包含 softmax,这将需要我使用 Kronecker delta 预先计算 softmax 导数。

或者我输入 d(CE)/d(CE) 即 torch.ones_like?

概念性的回答即可。

让我们尝试了解这两个选项的工作原理。

我们将使用此设置

import torch 
import torch.nn as nn
import numpy as np 
x = torch.rand((64,10), requires_grad=True)
net = nn.Sequential(nn.Linear(10,10))
labels = torch.tensor(np.random.choice(10, size=64)).long()
criterion = nn.CrossEntropyLoss()

第一个选项

loss = criterion(net(x), labels)
loss.backward(retain_graph=True)
dloss_dx = x.grad

请注意,您没有向梯度传递任何选项,因为损失是一个标量,如果您将损失计算为向量,那么您必须传递

第二个选项

dloss_dx2 = torch.autograd.grad(loss, x)

这将 return 一个元组,您可以使用第一个元素作为 x 的梯度。

请注意,如果您将多个输出作为元组传递,则 torch.autograd.grad return 是 dout/dx 的总和。但是由于 loss 是标量,你不需要传递 grad_outputs 因为默认情况下它会认为它是一个。