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