Градиент исчезает после первой эпохи в ручной линейной регрессии - PullRequest
0 голосов
/ 06 января 2019

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

Я пытаюсь обучить модели линейной регрессии, но продолжаю сталкиваться со следующей ошибкой,

---------------------------------------------------------------------- 

RuntimeError                              Traceback (most recent call last)
<ipython-input-80-ba5ca34a3a54> in <module>()
      9   loss = torch.dot(delta, delta)
     10 
---> 11   loss.backward()
     12   with torch.no_grad():
     13     w, b = w - learning_rate*w.grad.data, b - learning_rate*b.grad.data

/usr/local/lib/python3.6/dist-packages/torch/tensor.py in backward(self, gradient, retain_graph, create_graph)
     91                 products. Defaults to ``False``.
     92         """
---> 93         torch.autograd.backward(self, gradient, retain_graph, create_graph)
     94 
     95     def register_hook(self, hook):

/usr/local/lib/python3.6/dist-packages/torch/autograd/__init__.py in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables)
     87     Variable._execution_engine.run_backward(
     88         tensors, grad_tensors, retain_graph, create_graph,
---> 89         allow_unreachable=True)  # allow_unreachable flag
     90 
     91 

RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

И для справки, код здесь,

# dataset for training
X = torch.randn(100, 3)
y = -3*X[:,0] + 2.2*X[:,1] + 0.002*X[:,2] + 1

w = torch.randn(3, requires_grad=True, dtype=torch.float)  # model weights
b = torch.randn(1, requires_grad=True, dtype=torch.float)  # model bias


num_epochs = 10
learning_rate = 1e-4

for i in range(num_epochs):

  y_hat = torch.mv(X, w) + b
  delta = y_hat - y
  loss = torch.dot(delta, delta)

  loss.backward()
  with torch.no_grad():
    w, b = w - learning_rate*w.grad, b - learning_rate*b.grad

Кажется, проблема в том, что после первой эпохи атрибут градиента установлен на Нет, но я немного растерялся, почему это так.

Если я пытаюсь обнулить градиент после обновления весов, я получаю похожую ошибку.

1 Ответ

0 голосов
/ 06 января 2019

Ответ заключается в локальном отключении вычисления градиента . Как видно из первого примера, вычисления, выполняемые с помощью диспетчера контекста torch.no_grad(), приводят к тензорам, для которых requires_grad == False. Поскольку вы создаете «свежие» w и b вместо их обновления на месте, эти тензоры теряют свойство requires_grad после первой итерации, и вы получаете ошибку на 2-й итерации. Простое решение - включить градиенты

with torch.no_grad(): 
    w, b = w - learning_rate*w.grad, b - learning_rate*b.grad 
    w.requires_grad_(True) 
    b.requires_grad_(True) 

Если вы посмотрите источник оптимизаторов в модуле pytorch optim, например, SGD, вы увидите, что они используют операторы на месте, например add_. Вы можете переписать ваш цикл следующим образом

with torch.no_grad(): 
    w.sub_(learning_rate*w.grad)
    b.sub_(learning_rate*b.grad)

, который не будет касаться флага requires_grad, поскольку тензоры сохраняют свою «идентичность» - просто меняйте значения. В этом случае вам нужно будет не забывать вызывать w.zero_grad() и b.zero_grad() на каждой итерации, иначе значения градиента будут продолжать расти аддитивно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...