webentwicklung-frage-antwort-db.com.de

Wie debuggt man NaN-Werte in TensorFlow?

Ich habe TensorFlow ausgeführt und habe zufällig etwas mit einem NaN. Ich würde gerne wissen, was es ist, aber ich weiß nicht, wie ich das machen soll. Das Hauptproblem ist, dass ich in einem "normalen" prozeduralen Programm nur eine print-Anweisung schreiben würde, bevor die Operation ausgeführt wird. Das Problem mit TensorFlow ist, dass ich das nicht tun kann, weil ich das Diagramm zuerst deklariere (oder definiere), so dass das Hinzufügen von print-Anweisungen zur Diagrammdefinition nicht hilft. Gibt es Regeln, Ratschläge, Heuristiken, irgendetwas, um herauszufinden, was das NaN verursachen könnte?


In diesem Fall weiß ich genauer, auf welche Zeile ich schauen soll, weil ich Folgendes habe:

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) 

wenn diese Zeile vorhanden ist, gibt sie NaN zurück, wie von meinen Zusammenfassungsautoren angegeben. Warum ist das? Gibt es eine Möglichkeit, zumindest zu untersuchen, welchen Wert Z nach seiner Quadratwurzelbildung hat?


Für das spezifische Beispiel, das ich gepostet habe, habe ich tf.Print(0,Z) ausprobiert, aber ohne Erfolg wurde nichts gedruckt. Wie in:

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) 

Ich verstehe eigentlich nicht, was tf.Print Tun soll. Warum braucht es zwei Argumente? Wenn ich 1 Tensor drucken möchte, warum muss ich dann 2 bestehen? Scheint mir bizarr.


Ich habe mir die Funktion angeschaut tf.add_check_numerics_ops () , aber sie sagt nicht aus, wie man sie benutzt (außerdem scheinen die Dokumente nicht besonders hilfreich zu sein). Weiß jemand, wie man das benutzt?


Da Kommentare zu den Daten möglicherweise schlecht sind, verwende ich Standard-MNIST. Ich berechne jedoch eine positive Größe (paarweise eukledische Distanz) und verwurzele sie dann. Daher würde ich nicht sehen, wie die Daten speziell ein Problem darstellen würden.

43
Pinocchio

Es gibt verschiedene Gründe, warum Sie ein NaN-Ergebnis erhalten sollten. Oft liegt dies an einer zu hohen Lernrate, aber es gibt auch viele andere Gründe, wie zum Beispiel fehlerhafte Daten in Ihrer Eingabewarteschlange oder ein Protokoll mit 0 Berechnungen.

Wie auch immer, das Debuggen mit einem Ausdruck, wie Sie ihn beschreiben, kann nicht durch einen einfachen Ausdruck erfolgen (da dies nur zum Ausdruck der Tensor-Informationen innerhalb des Diagramms führen würde und keine tatsächlichen Werte ausgeben würde).

Wenn Sie jedoch tf.print als Befehl zum Bilden des Diagramms verwenden ( tf.print ), werden beim Ausführen des Diagramms die tatsächlichen Werte gedruckt (und es IS eine gute Übung, um diese Werte zu beobachten, um das Verhalten Ihres Netzes zu debuggen und zu verstehen).

Sie verwenden die print-Anweisung jedoch nicht ganz korrekt. Dies ist eine Operation, daher müssen Sie einen Tensor übergeben und einen Ergebnistensor anfordern, mit dem Sie später im ausführenden Diagramm arbeiten müssen. Andernfalls wird die Operation nicht ausgeführt und es wird nicht gedruckt. Versuche dies:

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)
22
Phillip Bock

Früher war es viel schwieriger, herauszufinden, wo die Nans und Infs auftreten können, als den Fehler zu beheben. Als Ergänzung zu @scais Antwort möchte ich hier einige Punkte hinzufügen:

Das Debug-Modul können Sie importieren durch:

from tensorflow.python import debug as tf_debug

ist viel besser als jeder Druck oder behaupten.

Sie können die Debug-Funktion einfach hinzufügen, indem Sie den Wrapper Ihrer Sitzung folgendermaßen ändern:

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

Und Sie fordern eine Befehlszeilenschnittstelle auf, dann geben Sie ein: run -f has_inf_or_nan und lt -f has_inf_or_nan um herauszufinden, wo die nans oder infs sind. Der erste ist der erste Ort, an dem die Katastrophe eintritt. Anhand des Variablennamens können Sie den Ursprung in Ihrem Code verfolgen.

Referenz: https://developers.googleblog.com/2017/02/debug-tensorflow-models-with-tfdbg.html

9
Lerner Zhang

Es sieht so aus, als könnten Sie es aufrufen, nachdem Sie das Diagramm fertiggestellt haben.

check = tf.add_check_numerics_ops()

Ich denke, dies wird die Prüfung für alle Gleitkommaoperationen hinzufügen. Anschließend können Sie in der Sitzungslauffunktion die Prüfoperation hinzufügen.

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

8
chasep255

Ab Version 0.12 wird TensorFlow mit einem integrierten Debugger namens tfdbg ausgeliefert. Es optimiert den Workflow beim Debuggen dieser Art von Problemen mit falschen numerischen Werten (wie inf und nan). Die Dokumentation finden Sie unter: https://www.tensorflow.org/programmers_guide/debugger

7
scai

Zunächst müssen Sie überprüfen, ob die eingegebenen Daten korrekt sind. In den meisten Fällen ist dies der Grund. Aber natürlich nicht immer.

Normalerweise benutze ich Tensorboard, um zu sehen, was während des Trainings passiert. So können Sie die Werte bei jedem Schritt mit sehen

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)

Sie können auch einfach den aktuellen Wert auswerten und ausdrucken:

 print(sess.run(Z))
3
Alex Joz

Ich konnte meine NaN-Probleme beheben, indem ich alle Dropout-Layer im Netzwerkmodell entfernt habe. Ich vermutete, dass aus irgendeinem Grund eine Einheit (ein Neuron?) Im Netzwerk zu viele Eingangsverbindungen verloren hatte (so dass sie nach dem Ausfall Null hatte). Als die Informationen durchgeleitet wurden, hatte sie einen Wert von NaN. Ich verstehe nicht, wie das bei Dropout = 0,8 auf Layern mit jeweils mehr als hundert Einheiten immer wieder passieren kann, daher wurde das Problem wahrscheinlich aus einem anderen Grund behoben. In beiden Fällen konnte ich das Problem beheben, indem ich die Dropout-Ebenen auskommentierte.

EDIT: Ups! Mir ist aufgefallen, dass ich nach meiner letzten Ausgabeebene eine Dropout-Ebene hinzugefügt habe, die aus drei Einheiten besteht. Das macht jetzt mehr Sinn. Also mach das nicht!

1
sOvr9000

Aktuelle Implementierung von tfdbg.has_inf_or_nan scheint nicht sofort zu brechen, wenn ein Tensor getroffen wird, der NaN enthält. Wenn es anhält, wird die große Liste der angezeigten Tensoren nicht in der Reihenfolge ihrer Ausführung sortiert. Ein möglicher Hack, um das erste Auftreten von Nans zu finden, besteht darin, alle Tensoren in einem temporären Verzeichnis abzulegen und anschließend zu untersuchen. Hier ist ein schnelles und schmutziges Beispiel , um das zu tun. (Angenommen, die NaNs erscheinen in den ersten Läufen)

0
Yuq Wang