Приветствую всех!
У меня был проект, в котором я должен генерировать язык с помощью Recurrent Neural Network.В начале я просто взял последовательность символов, подал их в RNN и взял вывод, чтобы вычислить потери.Проблема в том, что этот подход не сработал, как я ожидал.Фактически, это работало очень плохо, принимая во внимание тот факт, что сгенерированные последовательности были почти всегда в диапазоне 200-300, и я не мог генерировать длинные последовательности текста.
Единственное решение, которое работало для меня вэтот контекст заключался в том, чтобы вводить по одному символу за раз в нейронную сеть и вычислять потери после подачи следующего набора символов.
На мой взгляд, два подхода в основном одно и то же, но разница очевидна.
Если кто-то может объяснить эти результаты, это мне очень поможет.Я приведу фрагменты кода ниже:
Ввод представляет собой последовательность из 300 символов
Версия, которая работает
for index, (input, target, lengths) in enumerate(trainLoader):
loss = 0
input = Variable(input.to(device))
target = Variable(target.to(device))
hidden = model.init_hidden(input)
lengths = Variable(torch.tensor(lengths).to(device))
optimizer.zero_grad()
#Iterate over each character from the sequence, excluding the padding zeroes from the mini-batch
for c in range(input.size(1)):
[input[:,c].nonzero()].size(0)).shape)
output, hidden = model(input[:,c][input[:,c].nonzero()].contiguous(),
hidden.narrow(1, 0, input[:,c][input[:,c].nonzero()].size(0)).contiguous())
hidden = repackage_hidden(hidden)
loss += criterion(output, target[:,c][target[:,c].nonzero()])
loss.backward()
optimizer.step()
cummulative_loss += loss.item()
Версия, которая не дает удовлетворительногорезультат
for index, (input, target, lengths) in enumerate(trainLoader):
loss = 0
input = Variable(input.to(device))
target = Variable(target.to(device))
hidden = model.init_hidden(input)
lengths = Variable(torch.tensor(lengths).to(device))
optimizer.zero_grad()
output, _ = model(input)
#hidden = repackage_hidden(hidden)
loss = criterion(output, target)
loss.backward()
optimizer.step()
cummulative_loss += loss.item()
Также ниже приведен код генерации последовательности:
Настройка начального состояния ввода и слова ввода (мы используем «[START]»).
def sample_sentence():
words = list()
count = 0
model.eval()
with torch.no_grad():
previousWord = torch.LongTensor(1, 1).fill_(trainData.vocabulary['letter2id']['[START]'])
hidden = Variable(torch.zeros(6, 1, 300).to(device))
while True:
# Predict the next word based on the previous hidden state and previous word.
inputWord = torch.autograd.Variable(previousWord.to(device))
#print("Prediction: ")
predictions, newHidden = model(inputWord, hidden)
hidden = newHidden
#print("After prediction")
pred = torch.nn.functional.softmax(predictions.squeeze()).data.cpu().numpy().astype('float64')
pred = pred/np.sum(pred)
nextWordId = np.random.multinomial(1, pred, 1).argmax()
if nextWordId == 0:
continue
words.append(trainData.vocabulary['id2letter'][nextWordId])
# Setup the inputs for the next round.
previousWord.fill_(nextWordId)
# Keep adding words until the [END] token is generated.
if nextWordId == trainData.vocabulary['letter2id']['[END]']:
break
if count>10000:
break
count += 1
words.insert(0, '[START]')
return words
Заранее спасибо!