5

我试图得到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 交叉熵包含 softmax,这将需要我使用 Kronecker delta 预先计算 softmax 导数。

还是我放d(CE)/d(CE)哪个是torch.ones_like?

一个概念性的答案很好。

4

1 回答 1

2

让我们尝试了解这两个选项是如何工作的。

我们将使用此设置

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,因为默认情况下它会认为它是一个。

于 2019-01-13T05:26:20.040 回答