Получение градиента векторизованной функции в pytorch

Я новичок в PyTorch и хочу делать то, что считаю очень простым, но у меня много трудностей.

У меня есть функция sin(x) * cos(x) + x^2, и я хочу получить производную от этой функции в любой момент.

Если я сделаю это одним очком, он отлично работает как

x = torch.autograd.Variable(torch.Tensor([4]),requires_grad=True)
y = torch.sin(x)*torch.cos(x)+torch.pow(x,2)
y.backward()
print(x.grad) # outputs tensor([7.8545])

Однако я хочу иметь возможность передавать вектор как x и оценивать производную поэлементно. Например:

Input: [4., 4., 4.,]
Output: tensor([7.8545, 7.8545, 7.8545])

Но я не могу заставить это работать.

Я пробовал просто делать

x = torch.tensor([4., 4., 4., 4.], requires_grad=True)
out = torch.sin(x)*torch.cos(x)+x.pow(2)
out.backward()
print(x.grad)

Но я получаю сообщение об ошибке «RuntimeError: grad может быть неявно создан только для скалярных выходов».

Как мне настроить этот код для векторов?

Заранее спасибо,


person LivingRobot    schedule 18.04.2019    source источник


Ответы (1)


Здесь вы можете найти соответствующее обсуждение вашей ошибки.

По сути, когда вы вызываете backward() без аргументов, он неявно преобразуется в backward(torch.Tensor([1])), где torch.Tensor([1]) - это выходное значение, относительно которого вычисляются градиенты.

Если вы передадите 4 (или больше) входов, каждому потребуется значение, относительно которого вы вычисляете градиент. Вы можете явно передать torch.ones_like backward следующим образом:

import torch

x = torch.tensor([4.0, 2.0, 1.5, 0.5], requires_grad=True)
out = torch.sin(x) * torch.cos(x) + x.pow(2)
# Pass tensor of ones, each for each item in x
out.backward(torch.ones_like(x))
print(x.grad)
person Szymon Maszke    schedule 18.04.2019
comment
Потрясающие. Спасибо большое! - person LivingRobot; 18.04.2019