2016-12-23 3 views
0

erstens, ich bin mir nicht sicher, ob der Titel sehr gut ist, aber es war das Beste, was ich mit meinem Verständnis der Situation kommen könnte.Force-Kopie von Tensor beim Einreihen

Der Hintergrund ist, dass ich versuche zu verstehen, wie Warteschlangen in Tensorflow arbeiten und stieß auf das folgende Problem, das mich verwirrt.

Ich habe eine variable n, die ich mit einem tf.FIFOQueue enqueue und dann inkrementieren I die Variable. Dies wird mehrere Male wiederholt, und man würde ein ähnliches Ergebnis wie 0, 1, 2, ... erwarten. Beim Leeren der Warteschlange sind jedoch alle Werte gleich.

Genauer gesagt, ist der Code wie folgt:

from __future__ import print_function 

import tensorflow as tf 

q = tf.FIFOQueue(10, tf.float32) 

n = tf.Variable(0, trainable=False, dtype=tf.float32) 
inc = n.assign(n+1) 
enqueue = q.enqueue(n) 

init = tf.global_variables_initializer() 

sess = tf.Session() 
sess.run(init) 

sess.run(enqueue) 
sess.run(inc) 

sess.run(enqueue) 
sess.run(inc) 

sess.run(enqueue) 
sess.run(inc) 

print(sess.run(q.dequeue())) 
print(sess.run(q.dequeue())) 
print(sess.run(q.dequeue())) 

Was ich würde drucken erwarten:

0.0 
1.0 
2.0 

Stattdessen erhalte ich folgendes Ergebnis:

3.0 
3.0 
3.0 

Es scheint so, Ich schiebe einen Zeiger auf n in die Warteschlange, anstatt den tatsächlichen Wert, was ich will. Ich habe jedoch kein wirkliches Verständnis für Tensorflow-Interna, also läuft vielleicht noch etwas anderes?

versuchte ich

enqueue = q.enqueue(n) 

zu

enqueue = q.enqueue(tf.identity(n)) 

seit Antworten auf How can I copy a variable in tensorflow und In TensorFlow, what is tf.identity used for? gibt mir den Eindruck zu ändern, dass es helfen könnte, aber es ist nicht das Ergebnis ändern. Ich habe auch versucht, eine tf.control_dependencies() hinzuzufügen, aber wieder sind alle Werte gleich, wenn Sie die Warteschlange entfernen.

Edit: Die obige Ausgabe ist von der Ausführung des Codes auf einem Computer mit einer einzigen CPU, beim Versuch zu sehen, ob es einen Unterschied zwischen verschiedenen Versionen von Tensorflow gab, bemerkte ich, wenn ich den Code auf einem Computer mit CPU und ausführen GPU Ich bekomme das "erwartete" Ergebnis. In der Tat, wenn ich mit CUDA_VISIBLE_DEVICES = "" laufe, bekomme ich das obige Ergebnis, und mit CUDA_VISIBLE_DEVICES = "0" bekomme ich das "erwartete" Ergebnis.

+0

Ein anderes Workaround 'q.enqueue_many ([[n]])' anstelle von 'q.enqueue (n)', das nach Wert und nicht nach Verweis in die Warteschlange einreiht –

Antwort

3

Um einen nicht-Caching zu erzwingen lesen Sie

q.enqueue(tf.add(q, 0)) 

Dies tun kann, ist, was currently done durch die Batch-Normalisierung Schicht ist eine Kopie zu erzwingen.

Die Semantik, wie Variablen gelesen und referenziert werden, wird gerade überarbeitet, sodass sie vorübergehend nicht intuitiv sind. Insbesondere erwartete ich q.enqueue(v.read_value()) eine nicht-Caching-Lese zu zwingen, aber es nicht beheben Ihrem Beispiel auf TF 0.12rc1

Mit GPU Maschine variabel auf GPU setzt, während Queue CPU nur ist, so enqueue op erzwingt eine GPU -> CPU-Kopie.

0

Falls es hilft, habe ich festgestellt, dass die anderen Antworten trotz korrekt funktionieren sie nicht für alle dtypes.

Zum Beispiel das funktioniert gut mit Schwimmern oder Ints aber schlägt fehl, wenn n eine String-Tensor ist:

q.enqueue(tf.add(n, 0)) 

Dieser schlägt fehl, wenn die Warteschlange Tupel mit heterogenen Typen verwendet (zB Ints und Schwimmer):

q.enqueue_many([[n]]) 

Also, wenn Sie sich in jeder dieser Situationen gefangen sehen versuchen Sie stattdessen:

q.enqueue(tf.add(n, tf.zeros_like(n))) 
q.enqueue([tf.add(n, tf.zeros_like(n)) for n in t]) 

Das funktioniert auch für String-Tensor und heterogene Tupel-Typen:Oder ein Tupel t einzureihen.

Hoffe es hilft!

-

aktualisieren: es sieht aus wie tf.bool Typen mit tf.zeros_like funktionieren nicht(). Für diese kann eine explizite Umwandlung in einen Integer-Typ erforderlich sein.

Verwandte Themen