我正在尝试获取d(loss)/d(input)
。我知道我有2个选择。
第一个选项:
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 = ? )
我的问题是:如果我使用交叉熵损失,第二种选择应该以{{1}}的形式传递吗?
我放grad_outputs
吗?由于pytorch交叉熵包含softmax,这将需要我使用Kronecker delta预先计算softmax导数。
还是我放置d(CE)/d(y_hat)
就是torch.ones_like?
一个概念上的答案很好。
答案 0 :(得分:1)
让我们尝试了解这两个选项的工作方式。
我们将使用此设置
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)
这将返回一个元组,您可以将第一个元素用作x的渐变。
请注意,如果您将多个输出作为元组传递,则torch.autograd.grad
将返回dout / dx的总和。但是由于损失是标量,因此您不需要传递grad_outputs
,因为默认情况下它将被认为是一个。