Вы получаете упомянутую ошибку, потому что вы пытаетесь передать кусочек тензора X
: X[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)