Ich habe festgestellt, dass ein häufiges Auftreten während des Trainings NAN
eingeführt wird.
Oft scheint es durch Gewichte in inneren Produkt- / vollständig verbundenen oder Faltungsschichten, die explodieren, eingeführt zu werden.
Tritt dies auf, weil die Gradientenberechnung explodiert? Oder liegt es an der Gewichtsinitialisierung (wenn ja, warum hat die Gewichtsinitialisierung diesen Effekt)? Oder liegt es wahrscheinlich an der Art der Eingabedaten?
Die übergeordnete Frage lautet hier einfach: Was ist der häufigste Grund für das Auftreten von NANs während des Trainings? Und zweitens, was sind einige Methoden, um dies zu bekämpfen (und warum funktionieren sie)?
caffe
.Antworten:
Gute Frage.
Ich bin mehrmals auf dieses Phänomen gestoßen. Hier sind meine Beobachtungen:
Gradient explodieren
Grund: Große Farbverläufe bringen den Lernprozess aus der Bahn.
Was Sie erwarten sollten: Wenn Sie sich das Laufzeitprotokoll ansehen, sollten Sie sich die Verlustwerte pro Iteration ansehen. Sie werden feststellen, dass der Verlust von Iteration zu Iteration erheblich zunimmt. Schließlich ist der Verlust zu groß, um durch eine Gleitkommavariable dargestellt zu werden, und er wird
nan
.Was können Sie tun: Verringern Sie die
base_lr
(in der solver.prototxt) um eine Größenordnung (mindestens). Wenn Sie mehrere Verlustschichten haben, sollten Sie das Protokoll überprüfen, umloss_weight
festzustellen, welche Schicht für das Aufblasen des Gradienten verantwortlich ist, und die (in train_val.prototxt) für diese bestimmte Schicht anstelle der allgemeinen Schicht verringernbase_lr
.Schlechte Lernratenpolitik und Parameter
Grund: caffe kann keine gültige Lernrate berechnen und erhält
'inf'
oder'nan'
stattdessen multipliziert diese ungültige Rate alle Aktualisierungen und macht somit alle Parameter ungültig.Was Sie erwarten sollten: Wenn Sie sich das Laufzeitprotokoll ansehen, sollten Sie feststellen, dass die Lernrate selbst zum
'nan'
Beispiel wird:Was können Sie tun: Korrigieren Sie alle Parameter, die sich auf die Lernrate in Ihrer
'solver.prototxt'
Datei auswirken.Wenn Sie beispielsweise Parameter verwenden
lr_policy: "poly"
und vergessen, diese zu definierenmax_iter
, erhalten Sielr = nan
...Weitere Informationen zur Lernrate in caffe finden Sie in diesem Thread .
Fehlerhafte Verlustfunktion
Grund: Manchmal führen die Berechnungen des Verlusts in den Verlustschichten dazu, dass
nan
s angezeigt wird. Beispiel: FütterungsschichtInfogainLoss
mit nicht normalisierten Werten , Verwendung einer benutzerdefinierten Verlustschicht mit Fehlern usw.Was Sie erwarten sollten: Wenn Sie sich das Laufzeitprotokoll ansehen, werden Sie wahrscheinlich nichts Ungewöhnliches bemerken: Der Verlust nimmt allmählich ab und plötzlich
nan
erscheint ein.Was können Sie tun: Überprüfen Sie, ob Sie den Fehler reproduzieren können, fügen Sie der Verlustschicht einen Ausdruck hinzu und debuggen Sie den Fehler.
Zum Beispiel: Einmal habe ich einen Verlust verwendet, der die Strafe durch die Häufigkeit des Auftretens von Etiketten in einer Charge normalisiert hat. Es ist einfach so passiert, dass, wenn eines der Trainingsetiketten überhaupt nicht im Stapel erschien - der berechnete Verlust
nan
s erzeugt. In diesem Fall war es ausreichend, mit ausreichend großen Chargen (in Bezug auf die Anzahl der Etiketten im Satz) zu arbeiten, um diesen Fehler zu vermeiden.Fehlerhafte Eingabe
Grund: Sie haben eine Eingabe mit
nan
darin!Was Sie erwarten sollten: Sobald der Lernprozess "trifft", wird diese fehlerhafte Eingabe - Ausgabe
nan
. Wenn Sie sich das Laufzeitprotokoll ansehen, werden Sie wahrscheinlich nichts Ungewöhnliches bemerken: Der Verlust nimmt allmählich ab und plötzlichnan
erscheint ein.Was können Sie tun ? Erstellen Sie Ihre Eingabedatensätze (lmdb / leveldn / hdf5 ...) neu, und stellen Sie sicher, dass Ihr Trainings- / Validierungssatz keine fehlerhaften Bilddateien enthält. Für das Debuggen können Sie ein einfaches Netz erstellen, das die Eingabeebene liest, einen Dummy-Verlust aufweist und alle Eingaben durchläuft: Wenn eine davon fehlerhaft ist, sollte dieses Dummy-Netz auch erzeugen
nan
.Schritt größer als die Kernelgröße in der
"Pooling"
SchichtAus irgendeinem Grund kann die Auswahl von
stride
>kernel_size
für das Pooling zunan
s führen. Zum Beispiel:Ergebnisse mit
nan
s iny
.Instabilitäten in
"BatchNorm"
Es wurde berichtet, dass unter einigen Einstellungen die
"BatchNorm"
Schichtnan
aufgrund numerischer Instabilitäten s ausgeben kann .Dieses Problem wurde in bvlc / caffe angesprochen und PR # 5136 versucht, es zu beheben.
Vor kurzem wurde mir bewusst,
debug_info
Flagge: Einstellungdebug_info: true
in'solver.prototxt'
caffe Druck machen mehr Debug - Informationen (einschließlich Gradientengrößen und Aktivierungswerte) während des Trainings zu protokollieren: Diese Informationen können in Spek Gradienten blowups und andere Probleme in den Trainingsprozess helfen .quelle
In meinem Fall war es die Ursache, die Vorspannung in den Faltungs- / Entfaltungsschichten nicht einzustellen.
Lösung: Fügen Sie den Parametern der Faltungsschicht Folgendes hinzu.
Bias_Filler {Typ: "Konstante" Wert: 0}
quelle
Diese Antwort handelt nicht von einer Ursache für
nan
s, sondern schlägt einen Weg vor, um das Debuggen zu unterstützen. Sie können diese Python-Ebene haben:class checkFiniteLayer(caffe.Layer): def setup(self, bottom, top): self.prefix = self.param_str def reshape(self, bottom, top): pass def forward(self, bottom, top): for i in xrange(len(bottom)): isbad = np.sum(1-np.isfinite(bottom[i].data[...])) if isbad>0: raise Exception("checkFiniteLayer: %s forward pass bottom %d has %.2f%% non-finite elements" % (self.prefix,i,100*float(isbad)/bottom[i].count)) def backward(self, top, propagate_down, bottom): for i in xrange(len(top)): if not propagate_down[i]: continue isf = np.sum(1-np.isfinite(top[i].diff[...])) if isf>0: raise Exception("checkFiniteLayer: %s backward pass top %d has %.2f%% non-finite elements" % (self.prefix,i,100*float(isf)/top[i].count))
Das Hinzufügen dieser Ebene zu Ihrer
train_val.prototxt
an bestimmten Stellen, von denen Sie vermuten, dass sie Probleme verursachen können:quelle
learning_rate ist hoch und sollte verringert werden. Die Genauigkeit im RNN-Code war nan, wobei der niedrige Wert für die festgelegte Lernrate ausgewählt wird
quelle
Ich habe versucht, einen spärlichen Autoencoder zu bauen, und hatte mehrere Schichten darin, um Sparsamkeit zu induzieren. Während ich mein Netz betrieb, stieß ich auf die NaNs. Beim Entfernen einiger Schichten (in meinem Fall musste ich tatsächlich 1 entfernen) stellte ich fest, dass die NaNs verschwunden waren. Ich denke also, dass zu viel Sparsamkeit auch zu NaNs führen kann (einige 0/0-Berechnungen wurden möglicherweise aufgerufen!?)
quelle
nan
s und der festen Konfiguration angeben? Welche Art von Schichten? Welche Parameter?