2017-01-13 4 views
0

Ich habe einen Tensor in meinem Berechnungsdiagramm, dem ich nach jedem Zugschritt eine Zeile hinzufügen möchte. Wie kann ich das erreichen?Wie kann ich den Status vom Zugschritt zum Zugschritt beibehalten?

Mehr Details: Ich nehme Gradienten von optimizer.compute_gradients, und ich möchte diese Gradienten basierend auf dem Verlauf Verlauf ändern. Hier ist der Code, den ich zu verwenden ist versucht:

def process_gradient(gradient, optimizer, name): 
    reshaped_gradient = flatten(gradient) 

    if gradient.name in optimizer._slots: 
    optimizer._slots[gradient.name] += [reshaped_gradient] 
    else: 
    optimizer._slots[gradient.name] = [reshaped_gradient] 

    # each 
    gradients_over_time = tf.stack(optimizer._slots[gradient.name]) 

    print('gradients_over_time.get_shape()', gradients_over_time.get_shape()) 

    return gradient 

... 

grads_and_vars = optimizer.compute_gradients(cost_function) 
train_step = optimizer.apply_gradients([(process_gradient(grad, optimizer, str(i)), var) for i, (grad, var) in enumerate(grads_and_vars)]) 

ich auch um versucht habe, eine Variable zu halten, dass ich den Überblick über Reihen zu halten, indem verketten neue Zeilen auf, aber das hat nicht funktioniert.

+0

Sie könnten persistente Tensoren verwenden, um Tensoren zwischen Laufaufrufen zu speichern, siehe Lösung # 2 zum Beispiel Verwendung in http://stackoverflow.com/questions/41001298/decouple-dequeue-operation-from-gradient-loss-computation –

Antwort

0

Hier ist ein Beispiel für die Verwendung von persistenten Tensoren zum Speichern von Verlaufsverlauf. In der Schleife unter gradient_history zu Verkettung aller Steigungen bezieht sich so weit:

n = 2 
x = tf.Variable(tf.zeros((n,))) 
x_target = 10*tf.ones((n,)) 
loss = tf.reduce_sum(tf.square(x - x_target)) 
optimizer = tf.train.GradientDescentOptimizer(0.1) 
gradient = tf.gradients(loss, [x])[0] 
train_op = optimizer.apply_gradients([[gradient, x]]) 

# initialize history with first gradient 
sess = tf.Session() 
sess.run(tf.global_variables_initializer()) 
gradient_history0 = sess.run(tf.get_session_handle(tf.stack([gradient]))) 
previous_gradients_in, previous_gradients = tf.get_session_tensor(gradient_history0, dtype=dtype) 
gradient_history = tf.concat(0, [previous_gradients, [gradient]]) 
gradient_history_out = tf.get_session_handle(gradient_history) 

sess.run(tf.global_variables_initializer()) 

for i in range(10): 
    [gradient_history0, _, loss0, gradient0] = sess.run([gradient_history_out, train_op, loss, gradient], 
                feed_dict={previous_gradients_in: gradient_history0.handle}) 
    print(loss0, gradient0) 

Wenn Sie es ausführen, sollten Sie etwas sehen:

200.0 [-20. -20.] 
128.0 [-16. -16.] 
81.92 [-12.80000019 -12.80000019] 
52.4288 [-10.23999977 -10.23999977] 
33.5544 [-8.19199944 -8.19199944] 
21.4748 [-6.55359936 -6.55359936] 
13.7439 [-5.24287987 -5.24287987] 
8.79609 [-4.19430351 -4.19430351] 
5.6295 [-3.35544205 -3.35544205] 
3.60288 [-2.68435287 -2.68435287] 

Beachten Sie, dass Ihre Berechnung an jedem fed Schritt , gradient_history ist ein Tensor-Objekt, das sich auf die Verlaufsgeschichte bezieht. In der Zwischenzeit ist gradient_history0 ein TensorHandle-Objekt, das sich auf den gespeicherten Verlauf bezieht, der zwischen session.run-Aufrufen besteht. Sie können diesen Wert mit feed_dict={...: gradient_history0.handle} wieder in den Graphen eingeben, aber im Gegensatz zur Einspeisung von numpigen Arrays geben Sie einen "Zeiger" in die Daten ein, und die Daten selbst verlassen die TensorFlow-Laufzeit nicht. Da der Griff zwischen session.run Anrufe weiterhin besteht, können Sie es auch direkt bewerten:

In [10]: gradient_history0.eval() 
Out[10]: 
array([[-20.  , -20.  ], 
     [-20.  , -20.  ], 
     [-16.  , -16.  ], 
     [-12.80000019, -12.80000019], 
     [-10.23999977, -10.23999977], 
     [ -8.19199944, -8.19199944], 
     [ -6.55359936, -6.55359936], 
     [ -5.24287987, -5.24287987], 
     [ -4.19430351, -4.19430351], 
     [ -3.35544205, -3.35544205], 
     [ -2.68435287, -2.68435287]], dtype=float32) 
+0

Danke für deine Antwort. Derzeit analysiert es. Warum haben Sie "tf.gradients" anstelle von "optimizer.compute_gradients" verwendet? –

+0

Kein besonderer Grund, sie sollten gleich sein –

+0

Was ist der Zweck des Feed-Wörterbuchs in Ihrem Beispiel? –

1

landete ich dies mit tf.py_func bis zu erreichen. Ich verfolge den Status in einer globalen Liste, auf die in der Python-Funktion zugegriffen wird. Hier sind die Gradienten angewendet:

# process each individual gradient before applying it 
train_step = optimizer.apply_gradients([(process_gradient(grad, str(i)), var) for i, (grad, var) in enumerate(grads_and_vars)]) 

Hier ist, wo ich den Überblick über Zustand im Laufe der Zeit zu halten, und würde den aufgebauten Zustand verwenden:

def construct_processor(name): 
    global_gradients_over_time = {} 

    def python_process_gradient(gradient): 
    reshaped_gradient = gradient.flatten() 

    if name in global_gradients_over_time: 
     global_gradients_over_time[name].append(reshaped_gradient) 
    else: 
     global_gradients_over_time[name] = [reshaped_gradient] 

    # process gradients somehow 

    return gradient 

    return python_process_gradient 

def process_gradient(gradient, name): 
    return tf.py_func(construct_processor(name), [gradient], tf.float32) 

construct_processor ist es nur, damit Sie Steigungen ein verarbeiten Ich gebe jeder Gruppe von Gradienten einen Namen, damit ich sie im globalen Wörterbuch finden kann. Dieser Ansatz hält auch Speicher von der GPU, denke ich.

Verwandte Themen