Biorąc pod uwagę przykładowy kod .
Chciałbym wiedzieć, jak zastosować obcinanie gradientu w tej sieci w sieci RNN, gdzie istnieje możliwość eksplozji gradientów.
tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)
To jest przykład, który można wykorzystać, ale gdzie mam go wprowadzić? W obronie RNN
lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0)
# Split data because rnn cell needs a list of inputs for the RNN inner loop
_X = tf.split(0, n_steps, _X) # n_steps
tf.clip_by_value(_X, -1, 1, name=None)
Ale to nie ma sensu, ponieważ tensor _X jest wejściem, a nie gradem, który ma być przycięty?
Czy muszę w tym celu zdefiniować własny Optimizer, czy też istnieje prostsza opcja?
źródło
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
a następnie wykonywana jest iteracja optymalizatora,optimizer.run()
ale użycieoptimizer.run()
nie wydaje się działać w tym przypadku?optimizer.apply_gradients(capped_gvs)
x = optimizer.apply_gradients(capped_gvs)
x.run(...)
UserWarning: Converting sparse IndexedSlices to a dense Tensor with 148331760 elements. This may consume a large amount of memory.
Więc w jakiś sposób moje rzadkie gradienty są zamieniane na gęste. Masz pomysł, jak rozwiązać ten problem?tf.clip_by_global_norm
, jak sugeruje @danijarPomimo tego, co wydaje się popularne, prawdopodobnie chcesz przyciąć cały gradient według jego globalnej normy:
Przycinanie każdej macierzy gradientu indywidualnie zmienia ich względną skalę, ale jest również możliwe:
W TensorFlow 2 taśma oblicza gradienty, optymalizatory pochodzą z Keras i nie musimy przechowywać operacji aktualizacji, ponieważ działa ona automatycznie bez przekazywania jej do sesji:
źródło
clip_by_global_norm()
! Jest to również opisanethe correct way to perform gradient clipping
w dokumentach tensorflowtf.global_norm(gradients)
aby zobaczyć jego zwykły zakres, a następnie przycinać nieco powyżej tego, aby wartości odstające nie zepsuły treningu.opt.minimize()
po, czy zadzwoniłbyś do czegoś innego, jakopt.run()
sugeruje to w niektórych komentarzach do innych odpowiedzi?optimizer.minimize(loss)
to tylko skrót do obliczania i stosowania gradientów. Możesz uruchomić przykład w mojej odpowiedzi zsess.run(optimize)
.tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
funkcji eksperymentalnej, Twójoptimize
zastąpiłby mytrain_op
poprawny? Teraz moja,train_op = optimizer.minimize(loss, global_step=global_step))
więc próbuję się upewnić, że odpowiednio się dostosuję ...Faktycznie jest to właściwie wyjaśnione w dokumentacji. :
W podanym przez nich przykładzie wykorzystują te 3 kroki:
Oto
MyCapper
dowolna funkcja, która ogranicza twój gradient. Lista przydatnych funkcji (innych niżtf.clip_by_value()
) znajduje się tutaj .źródło
opt.minimize()
po, czy zadzwoniłbyś do czegoś innego, jakopt.run()
sugeruje to w niektórych komentarzach do innych odpowiedzi?opt.apply_gradients(...)
zmienną taką jaktrain_step
na przykład (tak jak w przypadkuopt.minimize()
. A w głównej pętli wywołujesz to jak zwykle, aby trenowaćsess.run([train_step, ...], feed_dict)
tf.clip_by_global_norm(list_of_tensors)
).Dla tych, którzy chcieliby zrozumieć ideę obcinania gradientu (według normy):
Za każdym razem, gdy norma gradientu jest większa niż określony próg, obcinamy normę gradientu tak, aby pozostawała w granicach progu. Ten próg jest czasami ustawiony na
5
.Niech gradient będzie równy g, a wartość max_norm_threshold będzie równa j .
Teraz, jeśli || g || > j , robimy:
g = ( j * g ) / || g ||
To jest implementacja wykonana w
tf.clip_by_norm
źródło
IMO najlepszym rozwiązaniem jest opakowanie twojego optymalizatora dekoratorem estymatora TF
tf.contrib.estimator.clip_gradients_by_norm
:W ten sposób musisz to zdefiniować tylko raz i nie uruchamiać go po każdym obliczeniu gradientu.
Dokumentacja: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm
źródło
Gradient Clipping zasadniczo pomaga w przypadku eksplodujących lub zanikających gradientów. Powiedzmy, że twoja strata jest zbyt duża, co spowoduje wykładnicze gradienty przepływające przez sieć, co może skutkować wartościami Nan. Aby temu zaradzić, obcinamy gradienty w określonym zakresie (od -1 do 1 lub w dowolnym zakresie zgodnie z warunkiem).
clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars
gdzie grads _and_vars to pary gradientów (które obliczasz za pomocą tf.compute_gradients) i ich zmienne, do których zostaną zastosowane.
Po obcięciu po prostu stosujemy jego wartość za pomocą optymalizatora.
optimizer.apply_gradients(clipped_value)
źródło