Это сработало, потому что расчет потерь происходил до no_grad
, и вы продолжаете вычислять градиенты в соответствии с этим расчетом потерь (в котором для расчета был включен градиент).
По сути, вы продолжаете обновлять вес ваших слоев, используя градиенты, рассчитанные за пределами no_grad
.
Когда вы на самом деле используете no_grad
:
for epoch in range(epochs):
# convert numpy to tensor
inputs = torch.from_numpy(x_train)
targets = torch.from_numpy(y_train)
with torch.no_grad(): # no_grad used here
# forward
out = model(inputs)
loss = criterion(out, targets)
model.zero_grad()
loss.backward()
optimizer.step()
print('inputs grad : ', inputs.requires_grad)
if epoch % 5 == 0:
print ('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, epochs, loss.item()))
Тогда вы получите правильную ошибку, сказав:
element 0 of tensors does not require grad and does not have a grad_fn
.
То есть вы используете no_grad
там, где это не подходит.
Если вы напечатаете .requires_grad
потери, то вы увидите, что потеря имеет requires_grad
.
То есть, когда вы сделаете это:
for epoch in range(epochs):
# convert numpy to tensor
inputs = torch.from_numpy(x_train)
targets = torch.from_numpy(y_train)
# forward
out = model(inputs)
loss = criterion(out, targets)
# backward
with torch.no_grad():
model.zero_grad()
loss.backward()
optimizer.step()
print('inputs grad : ', inputs.requires_grad)
print('loss grad : ', loss.requires_grad) # Prints loss.require_rgad
if epoch % 5 == 0:
print ('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, epochs, loss.item()))
Вы увидите:
inputs grad : False
loss grad : True
Кроме того,
print('inputs grad : ', inputs.requires_grad)
Будет всегда печать False
. То есть, если вы сделаете
for epoch in range(epochs):
# convert numpy to tensor
inputs = torch.from_numpy(x_train)
targets = torch.from_numpy(y_train)
print('inputs grad : ', inputs.requires_grad). # Print the inputs.requires_grad
# forward
out = model(inputs)
loss = criterion(out, targets)
# backward
with torch.no_grad():
model.zero_grad()
loss.backward()
optimizer.step()
print('inputs grad : ', inputs.requires_grad)
print('loss grad : ', loss.requires_grad)
if epoch % 5 == 0:
print ('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, epochs, loss.item()))
, вы получите:
inputs grad : False
inputs grad : False
loss grad : True
То есть вы используете неправильные вещи, чтобы проверить, что вы сделали неправильно. Лучшее, что вы можете сделать, это снова прочитать документы PyTorch по механике градиента.