2016-12-06 1 views
1

Ich versuche derzeit, die Verwendung von Feeds zu umgehen und Warteschlangen zu verwenden, um größere Datasets zu unterstützen. Die Verwendung von Warteschlangen funktioniert gut für die Optimierer in Tensorflow, da sie den Gradienten nur einmal für jede Auszugsoperation auswerten. Ich habe jedoch Interfaces mit anderen Optimizern implementiert, die Zeilensuchen durchführen, und ich muss nicht nur den Gradienten, sondern auch den Verlust an mehreren Punkten für denselben Batch auswerten. Leider wird bei dem normalen Warteschlangensystem jede Verlustauswertung eine Dequeue ausführen, anstatt für dieselbe Charge mehrere Male zu berechnen.Decouple Dequeue-Operation von Gradienten-/Verlustberechnung

Gibt es eine Möglichkeit, die Auslagerungsoperation von der Gradienten-/Verlustberechnung so zu entkoppeln, dass ich die Queue einmal ausführen und dann die Gradienten-/Verlustberechnung mehrmals im aktuellen Stapel ausführen kann?

Bearbeiten: Bitte beachten Sie, dass die Größe meiner Eingabe Tensor ist variabel zwischen den Chargen. Wir arbeiten mit molekularen Daten, und jedes Molekül hat eine andere Anzahl von Atomen. Das ist ziemlich anders als bei Bilddaten, bei denen normalerweise alle auf identische Dimensionen skaliert werden.

Antwort

2

Entkoppeln Sie es, indem Sie einen Wert für die Variablenspeicherauslagerung erstellen, und hängen Sie dann von dieser Variablen ab, anstatt die Operation aus der Warteschlange zu nehmen. während geschieht assign

Lösung 1 die Warteschlange Advancing: feste Größe Daten verwenden Variablen

(image_batch_live,) = tf.train.batch([image],batch_size=5,num_threads=1,capacity=614) 

image_batch = tf.Variable(
    tf.zeros((batch_size, image_size, image_size, color_channels)), 
    trainable=False, 
    name="input_values_cached") 

advance_batch = tf.assign(image_batch, image_batch_live) 

Jetzt image_batch neuesten Wert der Warteschlange gibt, ohne sie zu fort und advance_batch schreitet die Warteschlange.

Lösung # 2: variable Größe Daten verwenden persistent Tensoren

Hier entkoppeln wir den Workflow von dequeue_op und dequeue_op2 einzuführen. Die gesamte Berechnung hängt von dequeue_op2 ab, die den gespeicherten Wert von dequeue_op erhält. Die Verwendung von get_session_tensor/get_session_handle stellt sicher, dass die tatsächlichen Daten in der TensorFlow-Laufzeit verbleiben und der Wert, der über feed_dict übergeben wird, eine kurze Zeichenfolge ist. Die API ist ein wenig umständlich, weil dummy_handle, ich habe dieses Thema angesprochen here

import tensorflow as tf 
def create_session(): 
    sess = tf.InteractiveSession(config=tf.ConfigProto(operation_timeout_in_ms=3000)) 
    return sess 

tf.reset_default_graph() 

sess = create_session() 
dt = tf.int32 
dummy_handle = sess.run(tf.get_session_handle(tf.constant(1))) 
q = tf.FIFOQueue(capacity=20, dtypes=[dt]) 
enqueue_placeholder = tf.placeholder(dt, shape=[None]) 
enqueue_op = q.enqueue(enqueue_placeholder) 
dequeue_op = q.dequeue() 
size_op = q.size() 

dequeue_handle_op = tf.get_session_handle(dequeue_op) 
dequeue_placeholder, dequeue_op2 = tf.get_session_tensor(dummy_handle, dt) 
compute_op1 = tf.reduce_sum(dequeue_op2) 
compute_op2 = tf.reduce_sum(dequeue_op2)+1 


# fill queue with variable size data 
for i in range(10): 
    sess.run(enqueue_op, feed_dict={enqueue_placeholder:[1]*(i+1)}) 
sess.run(q.close()) 

try: 
    while(True): 
     dequeue_handle = sess.run(dequeue_handle_op) # advance the queue 
     val1 = sess.run(compute_op1, feed_dict={dequeue_placeholder: dequeue_handle.handle}) 
     val2 = sess.run(compute_op2, feed_dict={dequeue_placeholder: dequeue_handle.handle}) 
     size = sess.run(size_op) 
     print("val1 %d, val2 %d, queue size %d" % (val1, val2, size)) 
except tf.errors.OutOfRangeError: 
    print("Done") 

Sie sollten wie unten etwas sehen, wenn Sie es ausführen

val1 1, val2 2, queue size 9 
val1 2, val2 3, queue size 8 
val1 3, val2 4, queue size 7 
val1 4, val2 5, queue size 6 
val1 5, val2 6, queue size 5 
val1 6, val2 7, queue size 4 
val1 7, val2 8, queue size 3 
val1 8, val2 9, queue size 2 
val1 9, val2 10, queue size 1 
val1 10, val2 11, queue size 0 
Done 
+0

ich wahrscheinlich, dass die Größe erwähnt haben sollte Mein Eingangstensor ist in der ersten Dimension zwischen den Stapeln variabel. Das liegt daran, dass wir mit molekularen Daten arbeiten und dass die Moleküle im Gegensatz zu Bilddaten, bei denen alle Bilder eine feste Größe haben, unterschiedliche Atomzahlen haben. Also, ich glaube nicht, dass die Verwendung einer tf.Variable funktionieren wird, da diese eine feste Größe haben müssen. – mkmatlock

+0

Hm, wie benutzt du eine Warteschlange? Warteschlangen ähneln Variablen insofern, als sie einen Puffer fester Größe zuweisen. –

+0

Je nachdem, wie genau Ihr Problem strukturiert ist, gibt es viele Lösungen. Diese Frage würde also weitere Details erfordern. Im Allgemeinen sind 1) pad Dinge in eine Variable fester Größe passen, 2) verwenden Strings, die variable Menge von Daten in feste Dimension Tensor setzen können 3) Zwischenspeicher eine Zwischenstufe, die feste Größe ist statt variabler Größe Eingang 4) verwenden persistent Tensoren zum Speichern von Tensor variabler Größe zwischen Laufaufrufen –

Verwandte Themen