Considérant l' exemple de code .
Je voudrais savoir comment appliquer l'écrêtage de gradient sur ce réseau sur le RNN où il y a une possibilité d'explosion de gradients.
tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)
Ceci est un exemple qui pourrait être utilisé, mais où dois-je introduire cela? Dans la définition de 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)
Mais cela n'a pas de sens car le tenseur _X est l'entrée et non le grad ce qui doit être écrêté?
Dois-je définir mon propre optimiseur pour cela ou existe-t-il une option plus simple?
la source
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
et à mesure qu'une itération de l'optimiseur est effectuée,optimizer.run()
mais l'utilisationoptimizer.run()
ne semble pas fonctionner dans ce cas?optimizer.apply_gradients(capped_gvs)
doit être assigné à quelque chose,x = optimizer.apply_gradients(capped_gvs)
puis dans votre session, vous pouvez vous entraîner en tant quex.run(...)
UserWarning: Converting sparse IndexedSlices to a dense Tensor with 148331760 elements. This may consume a large amount of memory.
donc en quelque sorte mes dégradés clairsemés sont convertis en denses. Une idée comment surmonter ce problème?tf.clip_by_global_norm
, comme suggéré par @danijarMalgré ce qui semble être populaire, vous voulez probablement découper tout le dégradé selon sa norme globale:
Le découpage de chaque matrice de dégradé change individuellement leur échelle relative, mais est également possible:
Dans TensorFlow 2, une bande calcule les dégradés, les optimiseurs proviennent de Keras, et nous n'avons pas besoin de stocker l'opération de mise à jour car elle s'exécute automatiquement sans la transmettre à une session:
la source
clip_by_global_norm()
! Ceci est également décrit commethe correct way to perform gradient clipping
dans la documentation tensorflowtf.global_norm(gradients)
pour voir sa plage habituelle, puis de couper un peu au-dessus pour éviter que les valeurs aberrantes ne gâchent la formation.opt.minimize()
après ou appelleriez-vous quelque chose de différent comme celaopt.run()
est suggéré dans certains des commentaires sur d'autres réponses?optimizer.minimize(loss)
c'est juste un raccourci pour calculer et appliquer les dégradés. Vous pouvez exécuter l'exemple dans ma réponse avecsess.run(optimize)
.tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
dans une fonction d'expérimentation, alors votreoptimize
remplacerait montrain_op
correct? En ce moment,train_op = optimizer.minimize(loss, global_step=global_step))
j'essaye de m'assurer que je m'ajuste en conséquence ...Ceci est en fait correctement expliqué dans la documentation. :
Et dans l'exemple qu'ils fournissent, ils utilisent ces 3 étapes:
Voici
MyCapper
n'importe quelle fonction qui coiffe votre dégradé. La liste des fonctions utiles (autres quetf.clip_by_value()
) est ici .la source
opt.minimize()
après ou appelleriez-vous quelque chose de différent comme celaopt.run()
est suggéré dans certains des commentaires sur d'autres réponses?opt.apply_gradients(...)
à une variable commetrain_step
par exemple (comme vous le feriez pouropt.minimize()
. Et dans votre boucle principale, vous l'appelez comme d'habitude pour vous entraînersess.run([train_step, ...], feed_dict)
tf.clip_by_global_norm(list_of_tensors)
).Pour ceux qui voudraient comprendre l'idée de découpage en dégradé (par norme):
Chaque fois que la norme de gradient est supérieure à un seuil particulier, nous découpons la norme de gradient afin qu'elle reste dans le seuil. Ce seuil est parfois défini sur
5
.Soit le gradient g et le max_norm_threshold j .
Maintenant, si || g || > j , on fait:
g = ( j * g ) / || g ||
C'est l'implémentation faite dans
tf.clip_by_norm
la source
IMO, la meilleure solution consiste à envelopper votre optimiseur avec le décorateur d'estimateur de TF
tf.contrib.estimator.clip_gradients_by_norm
:De cette façon, vous ne devez le définir qu'une seule fois et ne pas l'exécuter après chaque calcul de dégradés.
Documentation: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm
la source
L'écrêtage de gradient aide essentiellement en cas d'explosion ou de disparition des gradients.Dis que votre perte est trop élevée, ce qui entraînera des gradients exponentiels à travers le réseau, ce qui peut entraîner des valeurs Nan. Pour surmonter cela, nous découpons les dégradés dans une plage spécifique (-1 à 1 ou toute plage selon les conditions).
clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars
où les grades _et_vars sont les paires de dégradés (que vous calculez via tf.compute_gradients) et leurs variables auxquelles ils seront appliqués.
Après le découpage, nous appliquons simplement sa valeur à l'aide d'un optimiseur.
optimizer.apply_gradients(clipped_value)
la source