wake-up-neo.com

Wie wende ich in TensorFlow Gradientenbeschneidung an?

Betrachtet man den Beispielcode .

Ich würde gerne wissen, wie man Gradienten-Clipping in diesem Netzwerk auf dem RNN anwendet, bei dem die Möglichkeit besteht, dass Gradienten explodieren.

tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)

Dies ist ein Beispiel, das verwendet werden könnte, aber wo stelle ich das vor? In der Def von 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)

Das macht aber keinen Sinn, da der Tensor _X der Eingang ist und nicht grad was abgeschnitten werden soll?

Muss ich dafür meinen eigenen Optimierer definieren oder gibt es eine einfachere Möglichkeit?

85
Arsenal Fanatic

Das Abschneiden von Verläufen muss erfolgen, nachdem die Verläufe berechnet wurden, bevor sie zum Aktualisieren der Modellparameter angewendet werden. In Ihrem Beispiel werden diese beiden Dinge von der AdamOptimizer.minimize() -Methode behandelt.

Um Ihre Verläufe zu beschneiden, müssen Sie sie explizit berechnen, beschneiden und anwenden, wie in dieser Abschnitt in der API-Dokumentation von TensorFlow beschrieben. Insbesondere müssen Sie den Aufruf der minimize() -Methode durch Folgendes ersetzen:

optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
gvs = optimizer.compute_gradients(cost)
capped_gvs = [(tf.clip_by_value(grad, -1., 1.), var) for grad, var in gvs]
train_op = optimizer.apply_gradients(capped_gvs)
129
Styrke

Ungeachtet dessen, was anscheinend beliebt ist, möchten Sie wahrscheinlich den gesamten Verlauf anhand der globalen Norm abschneiden:

optimizer = tf.train.AdamOptimizer(1e-3)
gradients, variables = Zip(*optimizer.compute_gradients(loss))
gradients, _ = tf.clip_by_global_norm(gradients, 5.0)
optimize = optimizer.apply_gradients(Zip(gradients, variables))

Wenn Sie jede Verlaufsmatrix einzeln beschneiden, ändert sich ihre relative Skalierung. Dies ist jedoch auch möglich:

optimizer = tf.train.AdamOptimizer(1e-3)
gradients, variables = Zip(*optimizer.compute_gradients(loss))
gradients = [
    None if gradient is None else tf.clip_by_norm(gradient, 5.0)
    for gradient in gradients]
optimize = optimizer.apply_gradients(Zip(gradients, variables))
104
danijar

Das ist eigentlich richtig erklärt in der Dokumentation. :

Mit dem Aufruf von minimieren () werden sowohl die Gradienten berechnet als auch auf die Variablen angewendet. Wenn Sie die Farbverläufe vor dem Anwenden verarbeiten möchten, können Sie den Optimierer stattdessen in drei Schritten verwenden:

  • Berechnen Sie die Farbverläufe mit compute_gradients ().
  • Bearbeiten Sie die Farbverläufe nach Ihren Wünschen.
  • Übernehmen Sie die verarbeiteten Farbverläufe mit apply_gradients ().

Und in dem Beispiel, das sie bereitstellen, verwenden sie diese 3 Schritte:

# Create an optimizer.
opt = GradientDescentOptimizer(learning_rate=0.1)

# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss, <list of variables>)

# grads_and_vars is a list of tuples (gradient, variable).  Do whatever you
# need to the 'gradient' part, for example cap them, etc.
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]

# Ask the optimizer to apply the capped gradients.
opt.apply_gradients(capped_grads_and_vars)

Hier ist MyCapper eine beliebige Funktion, die Ihren Verlauf begrenzt. Die Liste der nützlichen Funktionen (außer tf.clip_by_value()) ist hier .

9
Salvador Dali

Für diejenigen, die die Idee des Gradientenausschnitts (nach Norm) verstehen möchten:

Immer wenn die Gradientennorm größer als ein bestimmter Schwellenwert ist, beschneiden wir die Gradientennorm so, dass sie innerhalb des Schwellenwerts bleibt. Dieser Schwellenwert wird manchmal auf 5 Gesetzt.

Sei der Gradient g und die max_norm_threshold j.

Nun, wenn || g || > j machen wir:

g = ( j * g )/|| g ||

Dies ist die Implementierung in tf.clip_by_norm

7
kmario23

IMO ist die beste Lösung, Ihren Optimierer mit TF's Estimator Decorator tf.contrib.estimator.clip_gradients_by_norm Zu verpacken:

original_optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
optimizer = tf.contrib.estimator.clip_gradients_by_norm(original_optimizer, clip_norm=5.0)
train_op = optimizer.minimize(loss)

Auf diese Weise müssen Sie dies nur einmal definieren und nicht nach jeder Gradientenberechnung ausführen.

Dokumentation: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm

4
Ido Cohn

Gradient Clipping hilft grundsätzlich bei explodierenden oder verschwundenen Gradienten. Wenn Ihr Verlust zu hoch ist, können exponentielle Gradienten durch das Netzwerk fließen, was zu Nan-Werten führen kann. Um dies zu überwinden, schneiden wir Farbverläufe in einem bestimmten Bereich (-1 bis 1 oder in einem beliebigen Bereich gemäß Bedingung).

clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars

dabei sind grads _and_vars die Gradientenpaare (die Sie über tf.compute_gradients berechnen) und deren Variablen, auf die sie angewendet werden.

Nach dem Ausschneiden wenden wir den Wert einfach mit einem Optimierer an. optimizer.apply_gradients(clipped_value)

2
Raj