2017-05-05 8 views
2

sei angenommen, dass I einen Eingang tensor haben wie folgt:Wie wird ein Platzhalter variabler Länge in TensorFlow durchlaufen?

x_inputs = tf.placeholder(tf.float32, shape=[1, None], name='x_inputs') 

Dies ist ein Platzhalter mit variabler Länge Eingänge.

Außerdem habe ich einen Einbettungsmatrix:

embeddings = tf.Variable(
    tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0), 
    name='embeddings') 

Ich möchte, für jedes Element der Eingabesequenz, die Einbettungen nachzuschlagen und fügt sie zusammen einen einzigen Einbettungsvektor aufzubauen. Etwas Ähnliches (in Python):

embed = tf.zeros([batch_size, embedding_size]) 

for element in range(num_inputs): 
    embed += tf.nn.embedding_lookup(embeddings, 
            tf.cast(x_inputs[:, element], tf.int32)) 

Wenn num_inputs festgelegt ist, ist alles ok. Das Problem ist, dass der Wert num_inputs während des Trainings geändert wird und ich es innerhalb des Graphen berechnen muss. Ich weiß nicht, wie man das obige for loop im Diagramm basierend auf den Eingabewerten in x_inputs berechnet.

Antwort

3

tf.nn.embeddings_lookup kann variabler Größe Argumente behandeln:

x_inputs = tf.placeholder(tf.int32, shape=[1, None], name='x_inputs') 
embeddings = tf.constant([[1,2,3], [4,5,6], [7,8,9]]) 

iterSession = tf.InteractiveSession() 

embed = tf.squeeze(tf.nn.embeddings_lookup(embeddings, x_inputs)) 

iterSession.run(embed, feed_dict={x_inputs: [[0, 1, 0, 2]]}) 
# array([[1, 2, 3], 
#  [4, 5, 6], 
#  [1, 2, 3], 
#  [7, 8, 9]], dtype=int32) 

iterSession.run(tf.reduce_sum(embed, axis=0), feed_dict={x_inputs: [[0, 1, 0, 2]]}) 
# array([13, 17, 21], dtype=int32) 

Beachten Sie, dass x_inputs vom Typ tf.int32 direkt, die Besetzung zu vermeiden.


Wenn Sie die Länge dynamisch sein während der Ausführung und wurden unter Verwendung der Einbettungen als Beispiel wollen, können Sie es tf.foldl mit schreiben:

embed = tf.foldl(lambda a, x: a + tf.nn.embedding_lookup(embeddings, x), 
       tf.reshape(x_inputs, (-1,)), 
       initializer=[[0, 0, 0]]) 
iterSession.run(embed, feed_dict={x_inputs: [[0, 1, 0, 2]]}) 
# array([[13, 17, 21]], dtype=int32) 
+0

Danke. Ich verstehe nicht die Rolle von 'tf.squeeze', Ihr Code ist nicht kompatibel mit single-length-Eingaben, zum Beispiel: sess.run (tf.reduce_sum (einbetten, Achse = 0), feed_dict = {x_inputs: [[0] ]}) gibt "6" zurück! – AmirHJ

+0

@AmirHJ Ah, richtig. Ich hatte die "Squeeze" gedrückt, um eine einzelne 1-D-Achse zu entfernen. Allerdings agiert es standardmäßig gierig und entfernt alle gefundenen 1-dimensionalen Dimensionen. Wir können jedoch angeben, welche Achse in "tf.squeeze" (d. H. Der ersten Ebene) entfernt werden soll, und das sollte es auch mit 1-dimensionalen Eingaben kompatibel machen. –

+0

Ahaa, ist das Problem mit '' axis' Parameter tf.reduced_sum' ist, wird der endgültige Code wie folgt: 'bettet = tf.nn.embedding_lookup (Einbettungen, x_inputs)' 'und dann einzubetten = tf.reduce_sum (embeds , Achse = 1) ' Danke @musically_ut – AmirHJ