wake-up-neo.com

Häufige Ursachen für Nans während des Trainings

Ich habe festgestellt, dass ein häufiges Auftreten während des Trainings die Einführung von NANs 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)?

69
Aidan Gomez

Gute Frage.
Ich bin mehrmals auf dieses Phänomen gestoßen. Hier sind meine Beobachtungen:


Steigung sprengt

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.


Schlechte Lernratenpolitik und Params

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 .


Fehlerhafte Verlustfunktion

Grund: Manchmal werden bei der Berechnung des Verlusts in den Verlustebenen nans 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 nans 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.


Fehlerhafte Eingabe

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.


schritt größer als die Kernelgröße in der Ebene "Pooling"

Aus irgendeinem Grund kann die Auswahl von stride> kernel_size Für das Pooling zu nans führen. Beispielsweise:

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}

ergebnisse mit nans in y.


Instabilitäten in "BatchNorm"

Es wurde berichtet, dass unter einigen Einstellungen der Layer "BatchNorm" Aufgrund numerischer Instabilitäten nans 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 .

106
Shai

Diese Antwort handelt nicht von einer Ursache für nans, 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
  }
}
3
Shai

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}

3
izady