web-dev-qa-db-ja.com

トレーニング中のナンの一般的な原因

トレーニング中に頻繁に発生するのは、NANsが導入されていることです。

多くの場合、内積/完全に結合された層または畳み込み層の重みにより、爆発によって導入されるようです。

これは、勾配計算が爆発しているために発生していますか?または、それは重みの初期化のためですか(もしそうなら、なぜ重みの初期化がこの効果を持っているのでしょうか)?または、入力データの性質が原因である可能性がありますか?

ここでの包括的な質問は単純です:トレーニング中にNANが発生する最も一般的な理由は何ですか? そして、第二に、これと戦うためのいくつかの方法は何ですか?

69
Aidan Gomez

良い質問。
この現象に何度か遭遇しました。私の観察は次のとおりです。


勾配爆発

理由:勾配が大きいと学習プロセスが軌道から外れます。

期待すべきこと:ランタイムログを見て、反復ごとの損失値を調べる必要があります。損失は​​反復ごとに大幅に増加し始めます、最終的に損失は大きすぎて浮動小数点変数で表せず、nanになります。

あなたにできること:__solve.prototxt内のbase_lrを1桁以上(少なくとも)減らします。複数の損失層がある場合は、ログを調べて、勾配の爆発の原因となっている層を確認し、一般的なloss_weightではなく、その特定の層の(_train_val.prototxt内の)base_lrを減らします。


悪い学習率のポリシーとパラメーター

理由:caffeは有効な学習率の計算に失敗し、代わりに'inf'または'nan'を取得します。この無効な率はすべての更新を乗算し、すべてのパラメーターを無効にします。

期待すべきこと:ランタイムログを見ると、学習率自体が'nan'になっていることがわかります。次に例を示します。

... sgd_solver.cpp:106] Iteration 0, lr = -nan

あなたにできること:'solver.prototxt'ファイルの学習率に影響するすべてのパラメーターを修正します。
たとえば、lr_policy: "poly"を使用し、max_iterパラメーターを定義するのを忘れると、lr = nanになります...
caffeの学習率の詳細については、 このスレッド を参照してください。


障害損失機能

理由:損失レイヤーでの損失の計算により、nansが表示されることがあります。たとえば、フィード (正規化されていない値を持つInfogainLossレイヤー 、バグのあるカスタム損失レイヤーを使用するなど).

あなたが期待すべきこと:ランタイムログを見ると、おそらく異常なことに気付かないでしょう:損失は徐々に減少し、突然nanが表示されます。

あなたにできること:エラーを再現できるかどうかを確認し、損失層に印刷を追加してエラーをデバッグします。

例:一度バッチでラベルが発生する頻度でペナルティを正規化した損失を使用しました。トレーニングラベルの1つがバッチにまったく表示されなかった場合、計算された損失によりnansが生成されたのはまさにそのためです。その場合、このエラーを回避するには、十分な大きさのバッチ(セット内のラベルの数に関して)を処理するだけで十分です。


入力不良

理由:入力にnanが含まれています!

あなたが期待すべきこと:学習プロセスがこの障害のある入力を「ヒット」すると、出力はnanになります。ランタイムログを見ると、おそらく異常なことに気付かないでしょう。損失は徐々に減少しており、突然nanが表示されます。

あなたにできること:入力データセット(lmdb/leveldn/hdf5 ...)を再構築してください。トレーニング/検証セット。デバッグのために、入力層を読み取り、その上にダミー損失を持ち、すべての入力を実行する単純なネットを構築できます。入力の1つに障害がある場合、このダミーネットはnanも生成する必要があります。


"Pooling"レイヤーのカーネルサイズより大きいストライド

何らかの理由で、プーリングにstride> kernel_sizeを選択すると、nansが発生する場合があります。例えば:

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

nanysの結果。


"BatchNorm"の不安定性

一部の設定では、"BatchNorm"レイヤーが数値の不安定性によりnansを出力することがあると報告されました。
この issue はbvlc/caffeで発生し、 PR#5136 は修正を試みています。


最近、私は debug_info フラグに気づきました:debug_info: true'solver.prototxt'を設定すると、トレーニング中により多くのデバッグ情報(勾配の大きさやアクティベーション値を含む)を記録するためにcaffeが印刷されます:この情報は スポッティングに役立ちますグラディエントブローアップおよびトレーニングプロセスにおけるその他の問題

106
Shai

この答えはnansの原因に関するものではなく、デバッグを支援する方法を提案しています。このpythonレイヤーを使用できます:

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))

このレイヤーをtrain_val.prototxtに追加すると、問題が発生すると思われる特定のポイントで問題が発生する可能性があります。

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

私の場合、畳み込み/デコンボリューション層にバイアスを設定しないことが原因でした。

Solution:以下を畳み込み層パラメーターに追加します。

bias_filler {タイプ:「定数」値:0}

3
izady