2016-02-09 4 views
36

Ich versuche Adversarial NN zu implementieren, die erfordert, den einen oder anderen Teil des Graphen während alternierender Trainingsminibatches 'einzufrieren'. I.e. zwei Teilnetze: G und D."Einfrieren" einiger Variablen/Bereiche in Tensorflow: stop_gradient vs Variablen übergeben, um zu minimieren

G(Z) -> Xz 
D(X) -> Y 

wo Verlustfunktion von G auf D[G(Z)], D[X] abhängt.

Zuerst muss ich Parameter in D mit allen G Parameter festgelegt trainieren, und dann Parameter in G mit Parametern in D fixiert. Die Verlustfunktion im ersten Fall ist eine negative Verlustfunktion im zweiten Fall und die Aktualisierung muss für die Parameter des ersten oder zweiten Teilnetzes gelten.

sah ich, dass tensorflow tf.stop_gradient Funktion hat. Zum Zweck der Ausbildung der D (downstream) Sub-Netzwerk kann ich diese Funktion verwenden, um die Gradientenfluss zu

Z -> [ G ] -> tf.stop_gradient(Xz) -> [ D ] -> Y 

Die tf.stop_gradient ist sehr kurz und bündig kommentiert ohne in-line Beispiel zu blockieren (und Beispiel seq2seq.py ist zu lang und nicht, dass leicht zu lesen), sieht aber so aus, als müsste es während der Graphenerstellung aufgerufen werden. Bedeutet dies, dass ich das Diagrammmodell neu erstellen und neu initialisieren muss, wenn ich Gradientenfluss in alternierenden Batches blockieren/entsperren möchte?

Auch scheint es, dass man kann nicht den Gradientenblock fließt durch das Netzwerk G (upstream) mittels tf.stop_gradient, nicht wahr?

Als Alternative habe ich gesehen, dass man die Liste der Variablen an den Optimierer Anruf als opt_op = opt.minimize(cost, <list of variables>) übergeben kann, was eine einfache Lösung wäre, wenn man alle Variablen in den Bereichen jedes Subnetzes bekommen könnte. Kann man einen <list of variables> für ein tf.scope bekommen?

Antwort

43

Der einfachste Weg, dies zu erreichen, wie Sie in Ihrer Frage erwähnen, ist zwei Optimierer Operationen über separate Anrufe opt.minimize(cost, ...) zu erstellen. Standardmäßig verwendet das Optimierungsprogramm alle Variablen in tf.trainable_variables(). Wenn Sie die Variablen auf einen bestimmten Bereich filtern möchten, können Sie das optionale scope Argument tf.get_collection() wie folgt verwenden:

optimizer = tf.train.AdagradOptimzer(0.01) 

first_train_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 
            "scope/prefix/for/first/vars") 
first_train_op = optimizer.minimize(cost, var_list=first_train_vars) 

second_train_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 
             "scope/prefix/for/second/vars")      
second_train_op = optimizer.minimize(cost, var_list=second_train_vars) 
+5

Ich benutze dieses Rezept zum Trainieren, und wenn ich Graphen in "Tensorboard" untersuche, sehe ich, dass mein Graph verdoppelt wird, z. Ich bekomme "Gradienten" und "Gradienten_1". Ist das Ergebnis erwartet? –

10

Eine weitere Option, die Sie betrachten möchten vielleicht ist man trainierbar = False auf eine Variable festlegen. Was bedeutet, dass es nicht durch Training verändert wird.

tf.Variable(my_weights, trainable=False) 
+10

Das ist gut, wenn ich will es nicht zu überhaupt trainierbar sein. Ich möchte jedoch, dass es in jeder n-ten Epoche trainierbar ist. –

0

Ich weiß nicht, ob mein Ansatz Seiten hat nach unten, aber ich löste dieses Problem für mich mit diesem Konstrukt:

do_gradient = <Tensor that evaluates to 0 or 1> 
no_gradient = 1 - do_gradient 
wrapped_op = do_gradient * original + no_gradient * tf.stop_gradient(original) 

Also, wenn do_gradient = 1, werden die Werte und Verläufe durch ganz gut fließen, aber wenn do_gradient = 0, dann werden die Werte nur durch die stop_gradient op fließen, die die Steigungen zurückfließt zu stoppen.

Für mein Szenario Einhaken do_gradient auf einen Index eines random_shuffle Tensor up lassen Sie mich zufällig verschiedene Stücke von meinem Netzwerk zu trainieren.

+0

Dieser Ansatz löst ein anderes Problem als gefragt. Wenn Sie den Gradienten stoppen, wird keine der Variablen vor dieser Operation trainiert. Dies ist in einigen Fällen nützlich. Wenn Sie das nicht möchten, sollten Sie eine der anderen Antworten verwenden, da sie keine anderen Nebenwirkungen haben. –

12

@ Antwort mrry das ist völlig richtig und vielleicht allgemeinere als das, was ich gerade vorschlagen.Aber ich denke, eine einfachere Möglichkeit, es zu tun ist nur direkt die Python-Referenz übergeben zu var_list:

W = tf.Variable(...) 
C = tf.Variable(...) 
Y_est = tf.matmul(W,C) 
loss = tf.reduce_sum((data-Y_est)**2) 
optimizer = tf.train.AdamOptimizer(0.001) 

# You can pass the python object directly 
train_W = optimizer.minimize(loss, var_list=[W]) 
train_C = optimizer.minimize(loss, var_list=[C]) 

Ich habe ein in sich geschlossenes Beispiel hier: https://gist.github.com/ahwillia/8cedc710352eb919b684d8848bc2df3a

+0

danke! Dies ist eine direktere Lösungslösung, wenn Sie Ihre eigene Liste von Variablen in einer separaten Datenstruktur pflegen (Sie müssen sie also nicht durch Namen rückwärts durchsuchen (pro mrry solution) –

Verwandte Themen