web-dev-qa-db-ger.com

Wie erstelle ich eine Einbettungsschicht in Tensorflow RNN?

Ich baue ein RNN LSTM-Netzwerk auf, um Texte nach dem Alter der Autoren zu klassifizieren (binäre Klassifizierung - jung/erwachsen).

Scheint, als würde das Netzwerk nicht lernen und plötzlich eine Überanpassung beginnen:

 rnn_overfitting
Rot: Zug
Blau: Validierung

Eine Möglichkeit könnte sein, dass die Datendarstellung nicht gut genug ist. Ich habe nur die eindeutigen Wörter nach ihrer Häufigkeit sortiert und ihnen Indizes gegeben. Z.B.:

unknown -> 0
the     -> 1
a       -> 2
.       -> 3
to      -> 4

Also versuche ich, dies durch Word-Einbettung zu ersetzen. Ich habe einige Beispiele gesehen, kann sie aber nicht in meinen Code implementieren. Die meisten Beispiele sehen so aus:

embedding = tf.Variable(tf.random_uniform([vocab_size, hidden_size], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, input_data)

Bedeutet dies, dass wir eine Ebene erstellen, die lernt die Einbettung? Ich dachte, man sollte Word2Vec oder Glove herunterladen und das einfach benutzen.

Nehmen wir an, ich möchte diese Einbettungsebene erstellen ...
Wenn ich diese 2 Zeilen in meinem Code verwende, erhalte ich eine Fehlermeldung:

TypeError: Der an den Parameter 'Indizes' übergebene Wert enthält den Datentyp float32 nicht in der Liste der zulässigen Werte: int32, int64

Also muss ich wohl den input_data-Typ in int32 ändern. Also mache ich das (es sind immerhin alle Indizes) und ich bekomme Folgendes:

TypeError: Eingaben müssen eine Sequenz sein

Ich habe versucht, inputs (Argument für tf.contrib.rnn.static_rnn) mit einer Liste zu verpacken: [inputs], wie in diese Antwort vorgeschlagen, aber das hat einen anderen Fehler hervorgerufen:

ValueError: Die Eingabegröße (Dimension 0 der Eingaben) muss über Formschluss zugänglich sein, der Sägewert jedoch nicht.


Update:

Ich habe den Tensor x entstapelt, bevor ich ihn an embedding_lookup übergeben habe. Ich habe das Entstapeln nach dem Einbetten verschoben.

Aktualisierter Code:

MIN_TOKENS = 10
MAX_TOKENS = 30
x = tf.placeholder("int32", [None, MAX_TOKENS, 1])
y = tf.placeholder("float", [None, N_CLASSES]) # 0.0 / 1.0
...
seqlen = tf.placeholder(tf.int32, [None]) #list of each sequence length*
embedding = tf.Variable(tf.random_uniform([VOCAB_SIZE, HIDDEN_SIZE], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, x) #x is the text after converting to indices
inputs = tf.unstack(inputs, MAX_POST_LENGTH, 1)
outputs, states = tf.contrib.rnn.static_rnn(lstm_cell, inputs, dtype=tf.float32, sequence_length=seqlen) #---> Produces error

* seqlen: Ich habe die Sequenzen mit Nullen aufgefüllt, damit sie alle die gleiche Listengröße haben. Da sich die tatsächliche Größe jedoch unterscheidet, habe ich eine Liste erstellt, die die Länge ohne Auffüllung beschreibt.

Neuer Fehler:

ValueError: Eingabe 0 des Layers basic_lstm_cell_1 ist nicht kompatibel mit dem Layer: erwartet ndim = 2, gefunden ndim = 3. Volle Form erhalten: [Keine, 1, 64]

64 ist die Größe jeder verborgenen Ebene.

Es ist offensichtlich, dass ich ein Problem mit den Abmessungen habe ... Wie kann ich die Eingaben nach dem Einbetten an das Netzwerk anpassen?

7
Alaa M.

Aus dem tf.nn.static_rnn können wir die inputs-Argumente sehen: 

Eine Länge T Liste von Eingaben, jeweils ein Tensor der Form [batch_size, input_size]

Ihr Code sollte also so aussehen:

x = tf.placeholder("int32", [None, MAX_TOKENS])
...
inputs = tf.unstack(inputs, axis=1)
2
vijay m

tf.squeeze ist eine Methode, die Dimensionen der Größe 1 aus dem Tensor entfernt. Wenn das Endziel darin besteht, die Eingabeform als [Keine, 64] zu definieren, setzen Sie eine ähnliche Zeile wie inputs = tf.squeeze(inputs). Dies würde Ihr Problem beheben. 

1