Я следовал этому учебнику и попытался немного его изменить, чтобы увидеть, правильно ли я понимаю вещи. Однако когда я пытался использовать torch.opim.SGD
import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
device = torch.device("cuda:0")
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
w1 = torch.nn.Parameter(torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True))
w2 = torch.nn.Parameter(torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True))
lr = 1e-6
optimizer=torch.optim.SGD([w1,w2],lr=lr)
for t in range(500):
layer_1 = x.matmul(w1)
layer_1 = F.relu(layer_1)
y_pred = layer_1.matmul(w2)
loss = (y_pred - y).pow(2).sum()
print(t,loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
, моя потеря увеличивается до Inf на третьей итерации и до Nan после, что совершенно отличается от обновления вручную. Код для его обновления вручную находится ниже (также в учебной ссылке).
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
learning_rate = 1e-6
for t in range(500):
y_pred = x.mm(w1).clamp(min=0).mm(w2)
loss = (y_pred - y).pow(2).sum()
print(t, loss.item())
loss.backward()
with torch.no_grad():
w1 -= learning_rate * w1.grad
w2 -= learning_rate * w2.grad
w1.grad.zero_()
w2.grad.zero_()
Интересно, что не так с моей модифицированной версией (первый фрагмент). Когда я заменил SGD на Adam, результаты получились довольно хорошими (уменьшающиеся после каждой итерации, без Inf или Nan).