2017-11-02 4 views
2

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).

Antwort

1

Frage 1.

Lehrer zwingen, in diesem Fall implizit durchgeführt wird, da Ihr x_data ist [seq_len, batch_size] wird es in seq_len als Eingabe in jedem Element füttern und nicht die tatsächliche Ausgabe für den nächsten Einsatz Eingang.

Frage 2.

Ihr model.init_hidden jede Eingabe sieht es jedoch nicht nehmen, wie Sie versuchen, die Losgröße in, vielleicht könnten Sie, dass der Check hinzuzufügen, scheint alles andere in Ordnung. Sie müssen jedoch eine max() oder multinomiale() Ausgabe ausführen, bevor Sie sie wieder durchreichen können.

Frage 3.

Ja, dies zu tun, ist es ja schrecklich ineffizient. Dies ist eine Einschränkung des CUDNN LSTM-Kerns