Градиентный Спуск Питорха


Я пытаюсь вручную реализовать метод градиентного спуска в PyTorch в качестве упражнения. У меня есть следующие возможности для создания моего синтетического набора данных:

import torch
torch.manual_seed(0)
N = 100
x = torch.rand(N,1)*5
# Let the following command be the true function
y = 2.3 + 5.1*x
# Get some noisy observations
y_obs = y + 2*torch.randn(N,1)
Затем я создаю свою прогностическую функцию (y_pred), как показано ниже.
w = torch.randn(1, requires_grad=True)
b = torch.randn(1, requires_grad=True)
y_pred = w*x+b
mse = torch.mean((y_pred-y_obs)**2)

, который использует MSE для вывода Весов w,b. Я использую блок ниже, чтобы обновить значения в соответствии с градиентом.

gamma = 1e-2
for i in range(100):
  w = w - gamma *w.grad
  b = b - gamma *b.grad
  mse.backward()
Однако цикл работает только на первой итерации. вторая итерация вперед w.grad имеет значение None. я есть вполне уверен, что причина, по которой это происходит, заключается в том, что я устанавливаю w как функцию от него самого (я могу ошибаться).

Вопрос в том, как правильно обновить веса с помощью информации о градиенте?

1 3

1 ответ:

  1. Перед применением градиентного спуска следует вызвать обратный метод.
  2. вам нужно использовать новый вес для расчета потерь на каждой итерации.
  3. Создание нового тензора без градиентной ленты на каждой итерации.

Следующий код прекрасно работает на моем компьютере и получает w=5.1 & b=2.2 после 500 итераций обучения.

Код:

import torch
torch.manual_seed(0)
N = 100
x = torch.rand(N,1)*5
# Let the following command be the true function
y = 2.3 + 5.1*x
# Get some noisy observations
y_obs = y + 0.2*torch.randn(N,1)

w = torch.randn(1, requires_grad=True)
b = torch.randn(1, requires_grad=True)


gamma = 0.01
for i in range(500):
    print(i)
    # use new weight to calculate loss
    y_pred = w * x + b
    mse = torch.mean((y_pred - y_obs) ** 2)

    # backward
    mse.backward()
    print('w:', w)
    print('b:', b)
    print('w.grad:', w.grad)
    print('b.grad:', b.grad)

    # gradient descent, don't track
    with torch.no_grad():
        w = w - gamma * w.grad
        b = b - gamma * b.grad
    w.requires_grad = True
    b.requires_grad = True

Вывод:

499
w: tensor([5.1095], requires_grad=True)
b: tensor([2.2474], requires_grad=True)
w.grad: tensor([0.0179])
b.grad: tensor([-0.0576])