2016-02-09 4 views
36

Próbuję wprowadzić Adversarial NN, która wymaga "zamrożenia" jednej lub drugiej części wykresu podczas naprzemiennych mini-treningów. To znaczy. tam dwa podsieci G i D."Zamroź" niektóre zmienne/zakresy w tensorflow: stop_gradient vs przekazywanie zmiennych w celu zminimalizowania

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

którym funkcje straty G zależy D[G(Z)], D[X].

Najpierw muszę wyszkolić parametry w D z ustawionymi wszystkimi parametrami G, a następnie parametry w G z parametrami w D ustalonym. Funkcja utraty w pierwszym przypadku będzie funkcją straty ujemnej w drugim przypadku, a aktualizacja będzie musiała być zastosowana do parametrów pierwszej lub drugiej podsieci.

Widziałem, że funkcja tensorflow ma tf.stop_gradient. Dla celu przyuczenia D (poniżej) podsieci można używać tej funkcji do blokowania przepływu gradient do

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

The tf.stop_gradient bardzo krótko opatrzone bez przykład w linii (i przykład seq2seq.py zbyt długo i nie tak łatwe do odczytania), ale wygląda na to, że musi zostać wywołany podczas tworzenia wykresu. Czy to oznacza, że ​​jeśli chcę zablokować/odblokować przepływ gradientowy w naprzemiennych partiach, muszę ponownie utworzyć i ponownie zainicjować model wykresu?

Wygląda również na to, że nie można zablokować gradientu przepływającego przez sieć G (w górę) za pomocą tf.stop_gradient, prawda?

Jako alternatywę zobaczyłem, że można przekazać listę zmiennych do wywołania optymalizatora jako opt_op = opt.minimize(cost, <list of variables>), co byłoby łatwym rozwiązaniem, gdyby można było uzyskać wszystkie zmienne w zakresach każdej podsieci. Czy można uzyskać <list of variables> dla pliku tf.scope?

Odpowiedz

43

Najprostszym sposobem osiągnięcia tego celu, jak wspomina w swoim pytaniu, jest stworzenie dwóch operacji optymalizatora wykorzystaniem odrębnych połączeń do opt.minimize(cost, ...). Domyślnie optymalizator użyje wszystkich zmiennych w tf.trainable_variables(). Jeśli chcesz filtrować zmienne do określonego zakresu, można użyć opcjonalnego scope argument tf.get_collection() następująco:

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

Używam tego przepisu do treningu, a kiedy sprawdzam wykres w "tensorboardzie", widzę podwojenie mojego wykresu, np. Otrzymuję 'gradienty' i' gradient_1_1'. Czy oczekiwano wyniku? –

10

Inną opcją, którą możesz chcieć rozważyć, możesz ustawić trainable = False na zmiennej. Co oznacza, że ​​nie zostanie zmodyfikowany przez trening.

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

To jest dobre, jeśli nie chcę go do w ogóle można się szkolić. Jednak chcę, aby można było je trenować w każdej n-tej epoka. –

0

ja nie wiem, czy moje podejście ma na dół strony, ale rozwiązał ten problem za sobą z tego konstruktu:

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) 

Więc jeśli do_gradient = 1, wartości i gradienty popłynie przez dobrze, ale jeśli do_gradient = 0, wówczas wartości popłynie tylko poprzez op stop_gradient, która zatrzyma gradienty cofaniu.

Dla mojego scenariusza, zahaczenie do_gradienta do indeksu tensora random_shuffle pozwala mi losowo trenować różne elementy mojej sieci.

+0

To podejście rozwiązuje inny problem niż to, o co go zadano. Jeśli zatrzymasz gradient, to żadna z zmiennych sprzed tej operacji nie będzie przeszkolona. Jest to przydatne w niektórych przypadkach. Chyba że tego chcesz, lepiej użyć jednej z innych odpowiedzi, ponieważ nie mają innych efektów ubocznych. –

12

@ Odpowiedź mrry jest całkowicie słuszna i być może bardziej ogólna niż to, co zamierzam zasugerować.Ale myślę, że prostszy sposób, aby osiągnąć to, aby po prostu przekazać odwołanie Pythona bezpośrednio do 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]) 

mam samodzielne przykład tutaj: https://gist.github.com/ahwillia/8cedc710352eb919b684d8848bc2df3a

+0

dzięki! jest to bardziej bezpośrednie rozwiązanie rozwiązania, jeśli utrzymujesz własną listę zmiennych w osobnej strukturze danych (nie musisz więc odwracać-przeszukiwania ich poprzez nazwy (na rozwiązanie per mrry) –