Autograd.grad () для Tensor в pytorch

Я хочу вычислить градиент между двумя тензорами в сети. Входной тензор X (размер пакета x m) отправляется через набор сверточных слоев, которые возвращают мне и выводят тензор Y (размер пакета x n).

Я создаю новую потерю и хочу узнать градиент Y отн. X. Что-то такое в тензорном потоке:

tf.gradients(ys=Y, xs=X)

К сожалению, я проводил тесты с torch.autograd.grad(), но не мог понять, как это сделать. Я получаю такие ошибки: “RunTimeerror: grad can be implicitly created only for scalar outputs”.

Какими должны быть входы в torch.autograd.grad(), если я хочу знать градиент Y относительно. ИКС?


person Xbel    schedule 18.02.2019    source источник


Ответы (1)


Начнем с простого рабочего примера с простой функцией потерь и обычным обратным ходом. Мы построим короткий вычислительный граф и проведем на нем несколько градиентных вычислений.

Код:

import torch
from torch.autograd import grad
import torch.nn as nn


# Create some dummy data.
x = torch.ones(2, 2, requires_grad=True)
gt = torch.ones_like(x) * 16 - 0.5  # "ground-truths" 

# We will use MSELoss as an example.
loss_fn = nn.MSELoss()

# Do some computations.
v = x + 2
y = v ** 2

# Compute loss.
loss = loss_fn(y, gt)

print(f'Loss: {loss}')

# Now compute gradients:
d_loss_dx = grad(outputs=loss, inputs=x)
print(f'dloss/dx:\n {d_loss_dx}')

Выход:

Loss: 42.25
dloss/dx:
(tensor([[-19.5000, -19.5000], [-19.5000, -19.5000]]),)

Хорошо, это работает! Теперь попробуем воспроизвести ошибку «град может неявно создаваться только для скалярных выходов». Как видите, потери в предыдущем примере являются скалярами. backward() и grad() по умолчанию имеют дело с одним скалярным значением: loss.backward(torch.tensor(1.)). Если вы попытаетесь передать тензор с большим количеством значений, вы получите ошибку.

Код:

v = x + 2
y = v ** 2

try:
    dy_hat_dx = grad(outputs=y, inputs=x)
except RuntimeError as err:
    print(err)

Выход:

grad can be implicitly created only for scalar outputs

Следовательно, при использовании grad() вам необходимо указать параметр grad_outputs следующим образом:

Код:

v = x + 2
y = v ** 2

dy_dx = grad(outputs=y, inputs=x, grad_outputs=torch.ones_like(y))
print(f'dy/dx:\n {dy_dx}')

dv_dx = grad(outputs=v, inputs=x, grad_outputs=torch.ones_like(v))
print(f'dv/dx:\n {dv_dx}')

Выход:

dy/dx:
(tensor([[6., 6.],[6., 6.]]),)

dv/dx:
(tensor([[1., 1.], [1., 1.]]),)

ПРИМЕЧАНИЕ. Если вместо этого вы используете backward(), просто выполните y.backward(torch.ones_like(y)).

person trsvchn    schedule 19.02.2019