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, um loss_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 verringern base_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:
... sgd_solver.cpp:106] Iteration 0, lr = -nan
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 definieren max_iter
, erhalten Sie lr = 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ütterungsschicht InfogainLoss
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ötzlich nan
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"
Schicht
Aus irgendeinem Grund kann die Auswahl von stride
> kernel_size
für das Pooling zu nan
s führen. Zum Beispiel:
layer {
name: "faulty_pooling"
type: "Pooling"
bottom: "x"
top: "y"
pooling_param {
pool: AVE
stride: 5
kernel: 3
}
}
Ergebnisse mit nan
s in y
.
Instabilitäten in "BatchNorm"
Es wurde berichtet, dass unter einigen Einstellungen die "BatchNorm"
Schicht nan
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: Einstellung debug_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 .