良い質問。
私はこの現象に何度か遭遇しました。これが私の観察です:
グラデーションブローアップ
理由:大きな勾配は学習プロセスを軌道から外します。
期待すべきこと:ランタイムログを見ると、反復ごとの損失値を確認する必要があります。損失は反復ごとに大幅に増加し始め、最終的には損失が大きすぎて浮動小数点変数で表すことができなくなり、になりnan
ます。
あなたは何を行うことができます減らしますbase_lr
(少なくとも)桁(solver.prototxt中に)。複数の損失レイヤーがある場合は、ログを調べて、勾配の爆発の原因となっているレイヤーを確認し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
...
カフェでの学習率の詳細については、このスレッドを参照してください。
損失関数の障害
理由:損失レイヤーでの損失の計算により、nan
sが表示される場合があります。たとえば、InfogainLoss
正規化されていない値のフィードレイヤー、バグのあるカスタム損失レイヤーの使用などです。
期待すべきこと:ランタイムログを見ると、おそらく異常なことは何も気付かないでしょう。損失は徐々に減少し、突然突然nan
現れます。
何ができるか:エラーを再現できるかどうかを確認し、損失レイヤーにプリントアウトを追加して、エラーをデバッグします。
例:一度、バッチでのラベルの出現頻度によってペナルティを正規化する損失を使用しました。トレーニングラベルの1つがバッチにまったく表示されなかった場合、計算された損失によってnan
sが生成されました。その場合、(セット内のラベルの数に関して)十分な大きさのバッチで作業することで、このエラーを回避するのに十分でした。
入力不良
理由:入力がありますnan
!
期待すべきこと:学習プロセスがこの誤った入力に「ヒット」すると、出力はになりnan
ます。ランタイムログを見ると、おそらく異常なことは何も気付かないでしょう。損失は徐々に減少し、突然突然nan
現れます。
何ができるか:入力データセット(lmdb / leveldn / hdf5 ...)を再構築して、トレーニング/検証セットに不正な画像ファイルがないことを確認します。デバッグの場合、入力レイヤーを読み取り、その上にダミーの損失があり、すべての入力を実行する単純なネットを構築できます。それらの1つに障害がある場合、このダミーネットもを生成する必要がありnan
ます。
"Pooling"
レイヤーのカーネルサイズよりも大きいストライド
何らかの理由で、プーリングにstride
>kernel_size
を選択すると、nan
sが発生する場合があります。例えば:
layer {
name: "faulty_pooling"
type: "Pooling"
bottom: "x"
top: "y"
pooling_param {
pool: AVE
stride: 5
kernel: 3
}
}
結果はnan
sになりy
ます。
の不安定性 "BatchNorm"
一部の設定で"BatchNorm"
はnan
、数値が不安定なため、レイヤーがsを出力する場合があることが報告されました。
この問題はbvlc / caffeで発生し、PR#5136はそれを修正しようとしています。
最近、debug_info
フラグに気づきました。を設定debug_info: true
する'solver.prototxt'
と、トレーニング中により多くのデバッグ情報(勾配の大きさやアクティブ化値を含む)をログに記録するカフェプリントが作成されます。この情報は、トレーニングプロセスでの勾配の爆発やその他の問題の発見に役立ちます。