Ich habe festgestellt, dass ein häufiges Auftreten während des Trainings die Einführung von NAN
s ist.
Oft scheint es, als würde es durch das Aufblasen von Gewichten in das innere Produkt/vollständig verbundene Schichten oder Faltungsschichten eingeführt.
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)?
Gute Frage.
Ich bin mehrmals auf dieses Phänomen gestoßen. Hier sind meine Beobachtungen:
Grund: große Steigungen werfen 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 wird zu nan
.
Was können Sie tun: Verringern Sie den base_lr
(Im solver.prototxt) um eine Größenordnung (mindestens). Wenn Sie mehrere Loss-Layer haben, sollten Sie das Protokoll überprüfen, um festzustellen, welcher Layer für das Sprengen des Farbverlaufs verantwortlich ist, und den loss_weight
(In train_val.prototxt) für diesen bestimmten Layer anstelle des allgemeinen base_lr
.
Grund: caffe kann keine gültige Lernrate berechnen und erhält stattdessen 'inf'
Oder 'nan'
, Diese ungültige Rate multipliziert alle aktualisiert und damit alle Parameter ungültig.
Was Sie erwarten sollten: Wenn Sie sich das Laufzeitprotokoll ansehen, sollten Sie feststellen, dass die Lernrate selbst zu 'nan'
Wird, zum Beispiel:
... sgd_solver.cpp:106] Iteration 0, lr = -nan
Was können Sie tun: Korrigieren Sie alle Parameter, die die Lernrate beeinflussen, in Ihrer 'solver.prototxt'
- Datei.
Wenn Sie beispielsweise lr_policy: "poly"
Verwenden und vergessen, den Parameter max_iter
Zu definieren, erhalten Sie lr = nan
...
Weitere Informationen zur Lernrate in caffe finden Sie unter dieser Thread .
Grund: Manchmal werden bei der Berechnung des Verlusts in den Verlustebenen nan
s angezeigt. Beispiel: Feeding InfogainLoss
Layer mit nicht normalisierten Werten , Verwendung eines benutzerdefinierten Loss-Layers mit Bugs 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 ein nan
erscheint.
Was können Sie tun: Überprüfen Sie, ob Sie den Fehler reproduzieren können, fügen Sie dem Loss Layer 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 einem Stapel normalisiert hat. Es geschah einfach so, dass, wenn eines der Trainingsetiketten überhaupt nicht in der Charge auftauchte - der berechnete Verlust nan
s erzeugte. In diesem Fall war die Arbeit mit ausreichend großen Stapeln (in Bezug auf die Anzahl der Etiketten im Satz) ausreichend, um diesen Fehler zu vermeiden.
Grund: Sie haben eine Eingabe mit nan
!
Was Sie erwarten sollten: Sobald der Lernprozess "trifft", wird dieser fehlerhafte Ein-/Ausgang zu nan
. Wenn Sie sich das Laufzeitprotokoll ansehen, werden Sie wahrscheinlich nichts Ungewöhnliches bemerken: Der Verlust nimmt allmählich ab und plötzlich erscheint ein nan
.
Was können Sie tun: Erstellen Sie Ihre Eingabedatensätze (lmdb/leveldn/hdf5 ...) neu, und stellen Sie sicher, dass Sie keine fehlerhaften Bilddateien in Ihren Dateien haben Trainings-/Validierungsset. Zum Debuggen können Sie ein einfaches Netz erstellen, das die Eingabeebene liest, einen Dummy-Verlust darüber hat und alle Eingaben durchläuft. Wenn einer von ihnen fehlerhaft ist, sollte dieses Dummy-Netz auch nan
erzeugen.
"Pooling"
Aus irgendeinem Grund kann die Auswahl von stride
> kernel_size
Für das Pooling zu nan
s führen. Beispielsweise:
layer {
name: "faulty_pooling"
type: "Pooling"
bottom: "x"
top: "y"
pooling_param {
pool: AVE
stride: 5
kernel: 3
}
}
ergebnisse mit nan
s in y
.
"BatchNorm"
Es wurde berichtet, dass unter einigen Einstellungen der Layer "BatchNorm"
Aufgrund numerischer Instabilitäten nan
s ausgeben kann.
Dieses Problem wurde in bvlc/caffe angesprochen und PR # 5136 versucht, es zu beheben.
Vor kurzem wurde mir bewusst, dass debug_info
flag: Wenn Sie debug_info: true
In 'solver.prototxt'
Setzen, wird das Café gedruckt, um weitere Debug-Informationen (einschließlich Gradientengrößen und Aktivierung) zu protokollieren Werte) während des Trainings: Diese Informationen können beim Erkennen von Gradientenexplosionen und anderen Problemen im Trainingsprozess helfen .
Diese Antwort handelt nicht von einer Ursache für nan
s, sondern schlägt eine Möglichkeit vor, 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))
Hinzufügen dieser Ebene zu Ihrem train_val.prototxt
an bestimmten Stellen, von denen Sie vermuten, dass sie Probleme verursachen können:
layer {
type: "Python"
name: "check_loss"
bottom: "fc2"
top: "fc2" # "in-place" layer
python_param {
module: "/path/to/python/file/check_finite_layer.py" # must be in $PYTHONPATH
layer: "checkFiniteLayer"
param_str: "prefix-check_loss" # string for printouts
}
}
In meinem Fall war die Nichteinstellung der Vorspannung in den Faltungs-/Entfaltungsschichten die Ursache.
Lösung: Füge Folgendes zu den Parametern der Faltungsschicht hinzu.
bias_filler {Typ: "Konstante" Wert: 0}