Pytorch autograd.grad как записать параметры для нескольких выходов? - PullRequest
2 голосов
/ 23 сентября 2019

В документации из torch.autograd.grad указано, что для параметров

параметры:

выходы (последовательность Tensor) - выходыдифференцированной функции.

inputs (последовательность Tensor) - Входы, по которым градиент будет возвращен (а не накоплен в .grad).

Я пытаюсь сделать следующее:

a = torch.rand(2, requires_grad=True)
b = torch.rand(2, requires_grad=True)
c = a+b
d = a-b

torch.autograd.grad([c, d], [a, b]) #ValueError: only one element tensors can be converted to Python scalars
torch.autograd.grad(torch.tensor([c, d]), torch.tensor([a, b])) #RuntimeError: grad can be implicitly created only for scalar outputs

Я хотел бы получить градиенты списка тензоров с другим списком тензоров.Какой правильный способ подачи параметров?

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Как упомянуто torch.autograd.grad , torch.autograd.grad вычисляет и возвращает сумму градиентов выходов по входам.Поскольку ваши c и d не являются скалярными значениями, требуется grad_outputs.

import torch

a = torch.rand(2,requires_grad=True)
b = torch.rand(2, requires_grad=True)

a
# tensor([0.2308, 0.2388], requires_grad=True)

b
# tensor([0.6314, 0.7867], requires_grad=True)

c = a*a + b*b
d = 2*a+4*b

torch.autograd.grad([c,d], inputs=[a,b], grad_outputs=[torch.Tensor([1.,1.]), torch.Tensor([1.,1.])])
# (tensor([2.4616, 2.4776]), tensor([5.2628, 5.5734]))

Объяснение: dc/da = 2*a = [0.2308*2, 0.2388*2] dd/da = [2.,2.] Итак, первый вывод - dc/da*grad_outputs[0]+dd/da*grad_outputs[1] = [2.4616, 2.4776].Тот же расчет для второго выхода.

Если вы просто хотите получить градиент c и d по входам, вероятно, вы можете сделать это:

a = torch.rand(2,requires_grad=True)
b = torch.rand(2, requires_grad=True)

a
# tensor([0.9566, 0.6066], requires_grad=True)
b
# tensor([0.5248, 0.4833], requires_grad=True)

c = a*a + b*b
d = 2*a+4*b

[torch.autograd.grad(t, inputs=[a,b], grad_outputs=[torch.Tensor([1.,1.])]) for t in [c,d]]
# [(tensor([1.9133, 1.2132]), tensor([1.0496, 0.9666])),
# (tensor([2., 2.]), tensor([4., 4.]))]
0 голосов
/ 24 сентября 2019

Вот, пожалуйста, в приведенном вами примере:

a = torch.rand(2, requires_grad=True)
b = torch.rand(2, requires_grad=True)
loss = a + b

Поскольку потеря представляет собой вектор с 2 элементами, вы не можете выполнить операцию автоградации сразу.

обычно,

loss = torch.sum(a + b)
torch.autograd.grad([loss], [a, b])

Это вернет правильное значение градиента для тензора потерь, который содержит один элемент.Вы можете передать несколько скалярных тензоров в аргумент выходных данных метода torch.autograd.grad

...