59 votes

Comment déboguer les valeurs NaN dans TensorFlow?

J'étais en train de TensorFlow et j'ai justement quelque chose qui donne un NaN. J'aimerais savoir ce que c'est mais je ne sais pas comment faire. Le principal problème est que dans un "normal" de procédure du programme, je voudrais juste écrire une instruction print, juste avant l'opération est exécutée. Le problème avec TensorFlow est que je ne peux pas le faire parce que j'ai d'abord déclarer (ou définir) le graphique, afin d'ajouter des instructions d'impression du graphique, définition n'aide pas. Existe-il des règles, des conseils, des heuristiques, rien à traquer ce qui pourrait être la cause de l'NaN?


Dans ce cas je sais plus précisément ce qu'est la ligne de regarder parce que j'ai le texte suivant:

Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance
Z = tf.sqrt(Delta_tilde)
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)
A = tf.exp(Z) 

lorsque cette ligne est présente, j'ai ce qu'il renvoie NaN déclarée par mon résumé des écrivains. Pourquoi est-ce? Est-il un moyen d'explorer au moins quelle est la valeur de Z a, après sa place enracinée?


Pour l'exemple que j'ai posté, j'ai essayé d' tf.Print(0,Z) , mais sans succès, il imprimées rien. Comme dans:

Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance
Z = tf.sqrt(Delta_tilde)
tf.Print(0,[Z]) # <-------- TF PRINT STATMENT
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)
A = tf.exp(Z) 

En fait, je ne comprends pas ce qu' tf.Print est supposé faire. Pourquoi est-il besoin de deux arguments? Si je veux imprimer 1 tenseur pourquoi aurais-je besoin de passer 2? Me parait bizarre.


J'ai été à la recherche à la fonction tf.add_check_numerics_ops() mais elle ne dit pas comment l'utiliser (en plus des docs semblent pas être super utile). Personne ne sait comment l'utiliser?


Depuis que j'ai eu des commentaires sur les données peuvent être mauvais, je suis en utilisant la norme MNIST. Cependant, je suis d'informatique en une quantité qui est positif (pair-wise eucledian distance), puis place l'enracinement. Donc, je ne vois pas comment les données spécifiquement serait un problème.

27voto

friesel Points 1325

Il ya un couple de raisons POURQUOI vous pouvez obtenir un NaN-résultat, c'est souvent à cause d'une trop grande au taux d'apprentissage, mais beaucoup d'autres raisons sont possibles comme, par exemple, de corrompre les données de votre entrée de file d'attente ou un journal de 0 calcul.

De toute façon, le débogage avec une impression que vous décrivez ne peut pas être fait par un simple print (ainsi que dans l'impression de le tenseur des informations à l'intérieur de la courbe et de ne pas imprimer toutes les valeurs réelles).

Toutefois, si vous utilisez tf.imprimer comme une op dans le bâtiment, le graphique (tf.imprimer), puis lorsque le graphique est exécuté, vous obtiendrez les valeurs réelles de l'impression (et c'EST un bon exercice que de regarder ces valeurs à déboguer et à comprendre le comportement de votre net).

Cependant, vous êtes à l'aide de l'imprimé de déclaration pas entièrement dans la manière correcte. C'est un op, alors vous avez besoin pour passer un tenseur et demande un tenseur dont vous avez besoin pour travailler plus tard dans l'exécution graphique. Sinon, l'op ne va pas être exécutée et aucune impression se produit. Essayez ceci:

Z = tf.sqrt(Delta_tilde)
Z = tf.Print(Z,[Z], message="my Z-values:") # <-------- TF PRINT STATMENT
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)

17voto

leo adams Points 22

J'ai utilisé de trouver que c'est beaucoup plus difficile de déterminer avec précision où les nans et infs peut se produire que pour corriger le bug. Comme un complément au @scai réponse, j'aimerais ajouter quelques points ici:

Le module de débogage, vous pouvez importé par:

from tensorflow.python import debug as tf_debug

est beaucoup mieux que n'importe imprimer ou faire valoir.

Vous pouvez simplement ajouter les fonctions de débogage en changeant votre enveloppe de votre session par:

sess = tf_debug.LocalCLIDebugWrapperSession(sess)
sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan)

Et vous vous invite à une interface de ligne de commande, puis vous entrez: run -f has_inf_or_nan et lt -f has_inf_or_nan de trouver l'endroit où les nans ou infs sont. Le premier, c'est le premier endroit où la catastrophe se produit. Par le nom de la variable, vous pouvez retracer l'origine dans votre code.

Référence: https://developers.googleblog.com/2017/02/debug-tensorflow-models-with-tfdbg.html

11voto

scai Points 1023

À partir de la version 0.12, TensorFlow est livré avec un débogueur intégré appelé tfdbg . Il optimise le flux de travail de débogage de ce type de problèmes de valeur numérique erronée (tels que inf et nan ). La documentation est à: https://www.tensorflow.org/programmers_guide/debugger

9voto

chasep255 Points 5088

Il semble que vous puissiez l'appeler une fois que vous avez terminé de créer le graphique.

check = tf.add_check_numerics_ops()

Je pense que cela va ajouter la vérification pour toutes les opérations en virgule flottante. Ensuite, dans la fonction d'exécution de sessions, vous pouvez ajouter l'opération de vérification.

sess.run([check, ...])

5voto

Alex Joz Points 425

Tout d’abord, vous devez vérifier que vous entrez les données correctement. Dans la plupart des cas, c'est la raison. Mais pas toujours, bien sûr.

J'utilise habituellement Tensorboard pour voir ce qui se passe pendant l'entraînement. Ainsi, vous pouvez voir les valeurs sur chaque étape avec

 Z = tf.pow(Z, 2.0)    
summary_z = tf.scalar_summary('z', Z) 
#etc..
summary_merge = tf.merge_all_summaries()
#on each desired step save: 
    summary_str = sess.run(summary_merge)
    summary_writer.add_summary(summary_str, i)
 

Aussi, vous pouvez simplement évaluer et imprimer la valeur actuelle:

  print(sess.run(Z))
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X