Die Tutorials von pytorch sind hervorragend geeignet, um einen reinen RNN zu veranschaulichen, indem die Eingabe- und ausgeblendeten Ebenen definiert und die verborgenen Ebenen manuell in das Netzwerk zurückgeleitet werden, um den Status zu speichern. Diese Flexibilität ermöglicht es Ihnen dann, Lehrerübungen sehr einfach durchzuführen.Lehrer Forcing mit Pytorch RNN
Frage 1: Wie führen Sie Lehrer zwingen bei Verwendung der nativen nn.RNN()
Modul (da die gesamte Sequenz auf einmal zugeführt wird)? Beispiel einfache RNN Netzwerk wäre:
class SimpleRNN(nn.Module):
def __init__(self, vocab_size,
embedding_dim,
batch_sz,
hidden_size=128,
nlayers=1,
num_directions=1,
dropout=0.1):
super(SimpleRNN, self).__init__()
self.batch_sz = batch_sz
self.hidden_size = hidden_size
self.encoder = nn.Embedding(vocab_size, embedding_dim)
self.rnn = nn.RNN(embedding_dim, hidden_size, nlayers, dropout=0.5)
self.decoder = nn.Linear(hidden_size, vocab_size)
def init_hidden(self):
return autograd.Variable(torch.zeros(nlayers, batch_sz, hidden_size)).cuda()
def forward(self, inputs, hidden):
# -- encoder returns:
# -- [batch_sz, seq_len, embed_dim]
encoded = self.encoder(inputs)
_, seq_len, _ = encoded.size()
# -- rnn returns:
# -- output.size() = [seq_len, batch_sz, hidden_sz]
# -- hidden.size() = [nlayers, batch_sz, hidden_sz]
output, hidden = self.rnn(encoded.view(seq_len, batch_sz, embedding_dim), hidden)
# -- decoder returns:
# -- output.size() = [batch_sz, seq_len, vocab_size]
output = F.log_softmax(decoder(output.view(batch_sz, seq_len, self.hidden_size)))
return output, hidden
Wo ich das Netzwerk mit anrufen:
model = SimpleRNN(vocab_size, embedding_dim, batch_sz).cuda()
x_data, y_data = get_sequence_data(train_batches[0])
output, hidden = model(x_data, model.init_hidden())
Nur der Vollständigkeit halber, hier sind meine Formen von x_data
, output
und hidden
:
print(x_data.size(), output.size(), hidden.size())
torch.Size([32, 80]) torch.Size([32, 80, 4773]) torch.Size([1, 32, 128])
Frage 2: wäre es möglich, dieses SimpleRNN
Netzwerk dann zu verwenden Erzeugen Sie eine Sequenz Wort für Wort, indem Sie zuerst eine <GO_TOKEN>
und iterieren, bis eine <END_TOKEN>
erreicht ist? Ich frage, weil wenn ich laufe dies:
x_data = autograd.Variable(torch.LongTensor([[word2idx['<GO>']]]), volatile=True).cuda()
output, hidden = model(x_data, model.init_hidden(1))
print(output, output.sum())
ich ein output
alle 0s zu bekommen, und die output.sum() = 0
. Ich bekomme das auch nach dem Training des Netzwerks und der Rückübertragung des Verlustes. Irgendwelche Ideen warum?
Frage 3: Wenn nicht schrecklich ineffizient, ist es möglich, das SimpleRNN
Netzwerk über Wort-für-Wort, analog zu dem pytorch Tutorial gezeigt (hier) [http://pytorch.org/tutorials/intermediate/char_rnn_classification_tutorial.html] (wenn auch dort sie trainieren Zeichen-Zug -Charakter).