#python #pytorch #recurrent-neural-network
Вопрос:
Я тренирую PyTorch RNN на текстовом файле текстов песен, чтобы предсказать следующий персонаж, заданный персонажем.
Вот как определяется мой RNN:
import torch.nn as nn
import torch.optim
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
# from input, previous hidden state to new hidden state
self.i2h = nn.Linear(input_size hidden_size, hidden_size)
# from input, previous hidden state to output
self.i2o = nn.Linear(input_size hidden_size, output_size)
# softmax on output
self.softmax = nn.LogSoftmax(dim = 1)
def forward(self, input, hidden):
combined = torch.cat((input, hidden), 1)
#get new hidden state
hidden = self.i2h(combined)
#get output
output = self.i2o(combined)
#apply softmax
output = self.softmax(output)
return output, hidden
def initHidden(self):
return torch.zeros(1, self.hidden_size)
rnn = RNN(input_size = num_chars, hidden_size = 200, output_size = num_chars)
criterion = nn.NLLLoss()
lr = 0.01
optimizer = torch.optim.AdamW(rnn.parameters(), lr = lr)
Вот моя функция обучения:
def train(train, target):
hidden = rnn.initHidden()
loss = 0
for i in range(len(train)):
optimizer.zero_grad()
# get output, hidden state from rnn given input char, hidden state
output, hidden = rnn(train[i].unsqueeze(0), hidden)
#returns the index with '1' - indentifying the index of the right character
target_class = (target[i] == 1).nonzero(as_tuple=True)[0]
loss = criterion(output, target_class)
loss.backward(retain_graph = True)
optimizer.step()
print("done " str(i) " loop")
return output, loss.item() / train.size(0)
Когда я запускаю свою функцию обучения, я получаю эту ошибку:
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [274, 74]], which is output 0 of TBackward, is at version 5; expected version 3 instead. Hint: the backtrace further above shows the operation that failed to compute its gradient. The variable in question was changed in there or anywhere later. Good luck!
Интересно, что он проходит через два полных цикла функции обучения, прежде чем выдать мне эту ошибку.
Теперь, когда я удаляю retain_graph = True
из loss.backward()
, я получаю эту ошибку:
RuntimeError: Trying to backward through the graph a second time (or directly access saved variables after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad(). Specify retain_graph=True if you need to backward through the graph a second time or if you need to access saved variables after calling backward.
Здесь не следует пытаться несколько раз вернуться назад по графику. Возможно, график не очищается между циклами обучения?
Ответ №1:
Проблема в том, что вы накапливаете свои значения потерь (и в то же время связанные с ними графики вычислений) в переменной loss
, здесь:
loss = criterion(output, target_class)
В свою очередь, это означает, что на каждой итерации вы пытаетесь вернуться к текущим и предыдущим значениям потерь, которые были вычислены в предыдущих выводах. В данном конкретном случае, когда вы просматриваете свой набор данных, это неправильно.
Простое решение состоит в том, чтобы накопить loss
базовое значение, т. Е. скалярное значение, а не сам тензор, с помощью item
. И, обратное распространение на тензор текущих потерь:
total_loss = 0
for i in range(len(train)):
optimizer.zero_grad()
output, hidden = rnn(train[i].unsqueeze(0), hidden)
target_class = (target[i] == 1).nonzero(as_tuple=True)[0]
loss = criterion(output, target_class)
loss.backward()
total_loss = loss.item()
Поскольку вы обновляете параметр модели сразу после выполнения обратного распространения, вам не нужно сохранять график в памяти.
Комментарии:
1. Спасибо! Это сработало! Объяснение имеет смысл.