#pytorch #autograd
#pytorch #autograd
Вопрос:
Привет, я новичок в Pytorch. У меня есть простой модуль pytorch, где выход модуля представляет собой скалярную функцию потерь, которая зависит от производной некоторых полиномиальных функций. Допустим, результатом прямого прохода является: вход * производная (x ^ 2 y ^ 2) .
Один из способов реализовать это — явно записать производные от используемых полиномов и включить их в прямую модель. Итак, выход = входы * (2x 2y). Однако это ненадежно, поскольку, если я включу больше полиномов, мне придется вручную добавлять больше производных функций, что может занять много времени и привести к ошибкам.
Я хочу инициализировать полиномы, использовать Autograd для получения их производных, включить эту производную в формулу вывода. допустим, полиномиальная функция называется n . Я делаю n.backward(retain_graph=True) внутри прямого прохода. Однако, похоже, это не работает должным образом, поскольку я получаю очень разные ответы (о величине производных функции потерь по сравнению с параметрами модели), как при использовании аналитического выражения в прямом проходе.
Обратите внимание, что как выходные данные f.backward, так и аналитическое выражение производной совпадают. Таким образом, он правильно вычисляет производную от многочленов, но ему трудно связать это с конечной функцией потерь. Это означает, что вызов backward() также изменяет параметры модели, пытаясь получить производные для коэффициентов полинома. Я уверен, что это из-за моего плохого понимания pytorch, и добавление вызова f.backward() внутри прямого прохода каким-то образом портит вызов loss.backward() .
Вот упрощенный пример: проблема в том, что модель значений.learn.grad отличается при использовании аналитического метода и метода autograd .backward()
class Model(nn.Module):
def __init__(self, grin_type='radial',loss_type='analytic', device='cpu', dtype=torch.float32):
super(Model, self).__init__()
self.dtype=dtype
self.device=device
self.loss_type=loss_type
self.grin_type=grin_type
self.x=torch.tensor(2.,dtype = dtype, device=self.device) #mm
self.learn=nn.Parameter(torch.tensor(5.,dtype = dtype, device=self.device))
def forward(self,inputs,plotting=0):
if self.loss_type=='analytic':
outputs=inputs*self.learn*(2.*self.x)
elif self.loss_type=='autograd':
self.der=self.calc_derivative(self.x)
outputs=inputs*self.der
return outputs
def poly_fun(self,x):
return self.learn*torch.square(x)
def calc_derivative(self,x):
xn=x.clone().detach().requires_grad_(True)
n=self.poly_fun(xn)
dloss_dx=torch.autograd.grad(outputs=n, inputs=xn,create_graph=True)[0]*n/n
return dloss_dx
Комментарии:
1. Если я правильно понимаю, попробуйте использовать
x = x.detach().requires_grad_(True)
, тогда вы можете использоватьf = your_poly_fun(x)
иf.backward()
. Затем производная вашего полинома w.r.t.x
должна быть сохраненаx.grad
.detach
Здесь важно предотвратить распространение градиентов вплоть до параметров модели. Я не уверен, что этого будет полностью достаточно. Если вы опубликуете какой-нибудь минимальный пример кода, который работает с использованием выражений закрытой формы градиентов для вашего poly, это поможет.2. Спасибо за ваш ответ. Я только что добавил упрощенный пример. Оба метода autograd для получения производной от многочлена и аналитического решения совпадают. Но при использовании метода autograd кажется, что градиенты параметров модели также меняются. Есть ли у вас какие-либо предложения по предотвращению этого?
3. Я попытался запустить ваш код, но не могу найти никакой разницы в поведении, включая градиенты и график вычислений, между предоставленными вами методами autograd и analytical.
4. Кажется, что это работает сейчас. Большое спасибо за вашу помощь.