Was sind mögliche Fehlerwuellen von "nan" Values in neuronalen Netzen?

Einloggen oder registrieren, um einen Kommentar zu schreiben
Bayne
745
Bayne  

Was sind mögliche Fehlerwuellen von "nan" Values in neuronalen Netzen? Weiß das jemand?

habe datenlücken vorerst so ausgefüllt, dass sie einfach der row davor gleichgesetzt werden, sofern diese gültig ist. zudem habe ich die hidden layer von 5 auf 2 runtergeschraubt und an der learningrate gespielt.

Ich plane zudem von der Sigmoid auf die ReLU oder ELU umzusteigen... + Sollte NormalizeDouble() gegen "inf" values helfen ?


Gibt es ansonsten noch mögliche Auslöser für "nan" oder "inf"  Values in MQL5?

Carl Schreiber
Moderator
8151
Carl Schreiber  

Beide Fehler (nan, inf) zeigen auf Fehler in Deinem Code zB eine Division durch Null, die vom Code vorher(!) nicht abgefangen wurde.

Mehr zB. hier: https://de.wikipedia.org/wiki/NaN

NaN – Wikipedia
  • de.wikipedia.org
In der Informationstechnik steht NaN (englisch für „Not a Number“ – „Keine Zahl“) für einen numerischen Datentyp-Wert, der einem undefinierten oder nicht darstellbaren Wert entspricht, und kommt insbesondere bei Gleitkommazahlberechnungen vor. NaN erlangte systematische Verwendung mit der Einführung des IEEE-754-Gleitkommazahlenformats im Jahr...
Chris70
122
Chris70  

"Jein". Manche im mathematischen Sinne korrekte Operationen, die eine reelle Zahl ergeben, sind trotzdem in der Gleitkommaarithmetik unzulässig ( Division durch null würde hingegen ja auch mathematisch keine reelle Zahl ergeben). Dies hat mit den Limitationen der Zahlen in Bits zu tun:

Was genau bedeutet eine Zahl mit Double Genauigkeit aus Prozessor-Sicht? Nichts anderes als 8x8=64 Einsen und Nullen in der Codierung 1.11.52, soll heißen: wenn man eine binäre Zahl darstellt als 1.x mal 2 hoch Exponent, dann steht das erste Bit für das Vorzeichen, die nächsten 11 Bits für den Exponenten und die restlichen Bits für die sogenannte Mantisse (hier x), also die eigentliche Zahl (welche eine auf 11 binäre Nachkommastellen begrenzte Genauigkeit besitzt).

Viele Zahlen sind im mathematischen Sinne noch real, lassen sich jedoch so nicht darstellen.

In neuronalen Netzen können NaN's und Inf's auf nahezu allen Ebenen auftauchen. Auch die Ursachen sind vielfältig: ungeeignete Aktivierungsfunktion, ungeeignete Netzarchitektur, zu hohe learning rate, größere Dimensionsunterschiede unter den Inputs (daher Normalisierung) oder zwischen Bias-Intialisierung und Weight-Initialisierung....

Es bleibt einem daher nichts anderes übrig, als großzügig mit der MathIsValidNumber()-Funktion zu arbeiten. Nach dem Motto if (MathIsValidNumber(b+c)){a=b+c;} else {a=d;}. Was in diesem Fall als Wert von d vernünftig ist, ist von Fall zu Fall unterschiedlich und muss an konkrete Bedinungen geknüpft werden. Einfach eine Null oder Eins zu nehmen, kann zu funktionell irreversibel "toten" Neuronen führen. Man nimmt besser eine noch darstellbare Zahl,die halt recht nah an der mathematisch korrekten reellen Zahl ist. Beispiel Sigmoidfunktion mit asymptotischer Näherung an 1.0: da kann man dann z.B. double result=1-1e-16 nehmen. Oder in Fällen von asymptotischer Näherung an Null (wie in der Ableitung der ELU-Funktion) z.B. 1e-308. Neben den Aktivierungsfunktionen und deren Ableitungen sind inf-Errors typisch bei der Summation der gewichteten Inputs eines Neurons, nämlich wenn sehr große Zahlen addiert werden oder wenn ein sehr kleine Inputs des vorausgehenden Layers mit sehr kleinen Gewichten multipliziert werden. Da hilft ebenfalls auch nur eine MathIsValidNumber_Prüfung in Verbindung mit der Prüfung ob ein +inf oder -inf Ergebnis droht und dann halt das Ergebnis limitieren auf z.B. 1e308 oder 1e-308.Zusätzlich sollte man sich die auslösende Fehler-Stelle in eine eigene Variable hinterlegen (am einfachsten eine Beschreibung der Stelle in eine Stringvariable packen). So stürzt das Programm dann zwar nicht mehr ab, doch man hat die Möglichkeit, seine Hyperparameter oder die Normalisierung der Eingabeparameter anzupassen bis der Fehler nicht mehr vorkommt.

Bayne
745
Bayne  
Chris70:

"Jein". Manche im mathematischen Sinne korrekte Operationen, die eine reelle Zahl ergeben, sind trotzdem in der Gleitkommaarithmetik unzulässig ( Division durch null würde hingegen ja auch mathematisch keine reelle Zahl ergeben). Dies hat mit den Limitationen der Zahlen in Bits zu tun:

Was genau bedeutet eine Zahl mit Double Genauigkeit aus Prozessor-Sicht? Nichts anderes als 8x8=64 Einsen und Nullen in der Codierung 1.11.52, soll heißen: wenn man eine binäre Zahl darstellt als 1.x mal 2 hoch Exponent, dann steht das erste Bit für das Vorzeichen, die nächsten 11 Bits für den Exponenten und die restlichen Bits für die sogenannte Mantisse (hier x), also die eigentliche Zahl (welche eine auf 11 binäre Nachkommastellen begrenzte Genauigkeit besitzt).

Viele Zahlen sind im mathematischen Sinne noch real, lassen sich jedoch so nicht darstellen.

In neuronalen Netzen können NaN's und Inf's auf nahezu allen Ebenen auftauchen. Auch die Ursachen sind vielfältig: ungeeignete Aktivierungsfunktion, ungeeignete Netzarchitektur, zu hohe learning rate, größere Dimensionsunterschiede unter den Inputs (daher Normalisierung) oder zwischen Bias-Intialisierung und Weight-Initialisierung....

Es bleibt einem daher nichts anderes übrig, als großzügig mit der MathIsValidNumber()-Funktion zu arbeiten. Nach dem Motto if (MathIsValidNumber(b+c)){a=b+c;} else {a=d;}. Was in diesem Fall als Wert von d vernünftig ist, ist von Fall zu Fall unterschiedlich und muss an konkrete Bedinungen geknüpft werden. Einfach eine Null oder Eins zu nehmen, kann zu funktionell irreversibel "toten" Neuronen führen. Man nimmt besser eine noch darstellbare Zahl,die halt recht nah an der mathematisch korrekten reellen Zahl ist. Beispiel Sigmoidfunktion mit asymptotischer Näherung an 1.0: da kann man dann z.B. double result=1-1e-16 nehmen. Oder in Fällen von asymptotischer Näherung an Null (wie in der Ableitung der ELU-Funktion) z.B. 1e-308. Neben den Aktivierungsfunktionen und deren Ableitungen sind inf-Errors typisch bei der Summation der gewichteten Inputs eines Neurons, nämlich wenn sehr große Zahlen addiert werden oder wenn ein sehr kleine Inputs des vorausgehenden Layers mit sehr kleinen Gewichten multipliziert werden. Da hilft ebenfalls auch nur eine MathIsValidNumber_Prüfung in Verbindung mit der Prüfung ob ein +inf oder -inf Ergebnis droht und dann halt das Ergebnis limitieren auf z.B. 1e308 oder 1e-308.Zusätzlich sollte man sich die auslösende Fehler-Stelle in eine eigene Variable hinterlegen (am einfachsten eine Beschreibung der Stelle in eine Stringvariable packen). So stürzt das Programm dann zwar nicht mehr ab, doch man hat die Möglichkeit, seine Hyperparameter oder die Normalisierung der Eingabeparameter anzupassen bis der Fehler nicht mehr vorkommt.

Meinst du NormalizeDouble zu arbeiten macht auch Sinn?
Chris70
122
Chris70  

Nee.. NormalizeDouble dafür zu verwenden ist Quatsch; es ist wichtig, dass die Gewichte auch recht extreme Werte annehmen dürfen, zumindest am Anfang der Trainingsphase; da sind bei sehr kleinen Zahlen die vielen Nachkommastellen wichtig. NaNs sind aber vermeidbar.

Du kannst ja mal mit dem erwähnten Binär-Decoder spielen (im Strategy Tester starten, Pausieren um zu sehen, wie sich die Werte entwickeln), mit dem ich getestet habe; da wirst Du sehen, dass man mit "ungünstiger" Parameterauswahl NaN zuverlässig produzieren kann, mit anderen Einstellung aber auch gut vermeiden kann. Die Normalisierung der Eingabedaten entfällt hier allerdings, da Binärziffern ja nur 0 und 1 annehmen können. Das muss man bei "echten" Daten dann selbst machen (Skalierung, Mittelpunkt, evtl. Logarithmieren...).Interessanterweise ist ein Binärdecoder ein gutes Beispiel, dass bei neuronalen Netzen kompliziert nicht immer besser ist: die beste Netzarchitektur für diese Aufgabe wäre logisch überlegt GAR KEINE Hidden Layers (in meinem Beispielprogramm muss man die Hidden-Neuronen dann halt auf 1 setzen, damit die Information einfach durchgeleitet wird) und Ident(!)-Funktion als Aktivierungsfunktion, denn logisch betrachtet braucht man für diese Aufgabe keine nicht-lineare Funktion. Dann lernt das Netzwerk schnell Gewicht 1=1,Gewicht 2=2,Gewicht 3=4,Gewicht4=8,Gewicht 5=16.... usw.

Dateien:
MLP_test.ex5 54 kb
Einloggen oder registrieren, um einen Kommentar zu schreiben