使用autograd.grad()作为损失函数(pytorch)的参数

时间:2019-02-19 09:42:35

标签: python pytorch autograd

我想计算网络中两个张量之间的梯度。输入X张量通过一组卷积层发送,这些卷积层使我返回并输出Y张量。

我正在产生新的损失,我想知道范数(Y)w.r.t.之间的MSE。 X的每个元素。代码如下:

# Staring tensors
X = torch.rand(40, requires_grad=True)
Y = torch.rand(40, requires_grad=True)

# Define loss
loss_fn = nn.MSELoss()

#Make some calculations
V = Y*X+2

# Compute the norm
V_norm = V.norm()

# Computing gradient to calculate the loss
for i in range(len(V)):
    if i == 0:
        grad_tensor = torch.autograd.grad(outputs=V_norm, inputs=X[i])
    else:
        grad_tensor_ = torch.autograd.grad(outputs=V_norm, inputs=X[i])
        grad_tensor = torch.cat((grad_tensor, grad_tensor_), dim=0)

# Grund truth
gt = grad_tensor * 0 + 1

#Loss
loss_g = loss_fn(grad_tensor, gt)
print(loss_g) 

不幸的是,我一直在使用torch.autograd.grad()进行测试,但我不知道该怎么做。我收到以下错误消息:RuntimeError: One of the differentiated Tensors appears to not have been used in the graph. Set allow_unused=True if this is the desired behavior.

设置allow_unused=True会使我得到None的回馈,这是不可行的。不确定如何计算梯度和范数之间的损失。关于如何编码这种损失的任何想法?

1 个答案:

答案 0 :(得分:1)

您收到上述错误,是因为您试图将张量XX[i]馈送到grad(),并且它将被视为独立于张量的张量您的主要计算图。不确定,但似乎在执行切片时会返回新的张量。

但是您不需要for循环来计算渐变:

代码:

import torch
import torch.nn as nn

torch.manual_seed(42)

# Create some data.
X = torch.rand(40, requires_grad=True)
Y = torch.rand(40, requires_grad=True)

# Define loss.
loss_fn = nn.MSELoss()

# Do some computations.
V = Y * X + 2

# Compute the norm.
V_norm = V.norm()

print(f'V norm: {V_norm}')

# Computing gradient to calculate the loss
grad_tensor = torch.autograd.grad(outputs=V_norm, inputs=X)[0]  # [0] - Because grad returs tuple, so we need to unpack it
print(f'grad_tensor:\n {grad_tensor}')

# Grund truth
gt = grad_tensor * 0 + 1

loss_g = loss_fn(grad_tensor, gt)
print(f'loss_g: {loss_g}')

输出:

V norm: 14.54827

grad_tensor:
    tensor([0.1116, 0.0584, 0.1109, 0.1892, 0.1252, 0.0420, 0.1194, 0.1000, 0.1404,
            0.0272, 0.0007, 0.0460, 0.0168, 0.1575, 0.1097, 0.1120, 0.1168, 0.0771,
            0.1371, 0.0208, 0.0783, 0.0226, 0.0987, 0.0512, 0.0929, 0.0573, 0.1464,
            0.0286, 0.0293, 0.0278, 0.1896, 0.0939, 0.1935, 0.0123, 0.0006, 0.0156,
            0.0236, 0.1272, 0.1109, 0.1456])

loss_g: 0.841885

应届毕业生与正常人之间的亏损

您还提到要计算梯度和范数之间的损失,这是可能的。并且有两个可能的选择:

您希望将损失计算包括在计算图中,在这种情况下,请使用:

loss_norm_vs_grads = loss_fn(torch.ones_like(grad_tensor) * V_norm, grad_tensor)

您只想计算损失,并且不想从损失开始倒退,在这种情况下,请不要忘记使用torch.no_grad(),否则autograd将跟踪此更改并添加损失计算到您的计算图。

with torch.no_grad():
    loss_norm_vs_grads = loss_fn(torch.ones_like(grad_tensor) * V_norm, grad_tensor)