Градиентный Спуск Питорха
Я пытаюсь вручную реализовать метод градиентного спуска в 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 ответ:
- Перед применением градиентного спуска следует вызвать обратный метод.
- вам нужно использовать новый вес для расчета потерь на каждой итерации.
- Создание нового тензора без градиентной ленты на каждой итерации.
Следующий код прекрасно работает на моем компьютере и получает 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])