我的网络训练有素。我想计算输出功率的斜率输入。通过查询PyTorch文档, torch.autograd.grad 可能会有用。 因此,我使用以下代码:
x_test = torch.randn(D_in,requires_grad=True)
y_test = model(x_test)
d = torch.autograd.grad(y_test, x_test)[0]
model
是神经网络。 x_test
是大小为D_in
的输入,而y_test
是标量输出。
我想将计算结果与scipy.misc.derivative
的数值差进行比较。
因此,我通过设置索引来计算偏导数。
idx = 3
x_test = torch.randn(D_in,requires_grad=True)
y_test = model(x_test)
print(x_test[idx].item())
d = torch.autograd.grad(y_test, x_test)[0]
print(d[idx].item())
def fun(x):
x_input = x_test.detach()
x_input[idx] = x
with torch.no_grad():
y = model(x_input)
return y.item()
x0 = x_test[idx].item()
print(x0)
print(derivative(fun, x0, dx=1e-6))
但是我得到了完全不同的结果。
torch.autograd.grad
计算出的梯度为-0.009522666223347187
,
而scipy.misc.derivative
的数字是-0.014901161193847656
。
计算是否有问题?还是我误用了torch.autograd.grad
?
答案 0 :(得分:0)
实际上,您给定的代码很可能是完全正确的。 让我通过将您重定向到有关反向传播的一些背景信息(或在本例中为自动差分(AutoDiff))来说明这一点。
许多软件包的特定实现基于AutoGrad,AutoGrad是获取函数/图形的 exact 派生类的常用技术。它可以通过实质上“反转”正向计算过程来计算原子功能块的分段导数(例如加法,减法,乘法,除法等),然后“将它们链接在一起”来完成此操作。
我在this question的更详细的答案中解释了AutoDiff及其详细信息。
相反,通过使用有限差分,scipy的导数函数只是对该导数的逼近。您将在附近的点获取函数的结果,然后基于这些点的函数值之差来计算导数。这就是为什么您会看到两个梯度略有不同的原因,因为这可能是对实际导数的不准确表示。