トレーニング中に頻繁に発生するのは、NAN
sが導入されていることです。
多くの場合、内積/完全に結合された層または畳み込み層の重みにより、爆発によって導入されるようです。
これは、勾配計算が爆発しているために発生していますか?または、それは重みの初期化のためですか(もしそうなら、なぜ重みの初期化がこの効果を持っているのでしょうか)?または、入力データの性質が原因である可能性がありますか?
ここでの包括的な質問は単純です:トレーニング中にNANが発生する最も一般的な理由は何ですか? そして、第二に、これと戦うためのいくつかの方法は何ですか?
良い質問。
この現象に何度か遭遇しました。私の観察は次のとおりです。
理由:勾配が大きいと学習プロセスが軌道から外れます。
期待すべきこと:ランタイムログを見て、反復ごとの損失値を調べる必要があります。損失は反復ごとに大幅に増加し始めます、最終的に損失は大きすぎて浮動小数点変数で表せず、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の学習率の詳細については、 このスレッド を参照してください。
理由:損失レイヤーでの損失の計算により、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
のy
sの結果。
"BatchNorm"
の不安定性一部の設定では、"BatchNorm"
レイヤーが数値の不安定性によりnan
sを出力することがあると報告されました。
この issue はbvlc/caffeで発生し、 PR#5136 は修正を試みています。
最近、私は debug_info
フラグに気づきました:debug_info: true
に'solver.prototxt'
を設定すると、トレーニング中により多くのデバッグ情報(勾配の大きさやアクティベーション値を含む)を記録するためにcaffeが印刷されます:この情報は スポッティングに役立ちますグラディエントブローアップおよびトレーニングプロセスにおけるその他の問題 。
この答えはnan
sの原因に関するものではなく、デバッグを支援する方法を提案しています。この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
}
}
私の場合、畳み込み/デコンボリューション層にバイアスを設定しないことが原因でした。
Solution:以下を畳み込み層パラメーターに追加します。
bias_filler {タイプ:「定数」値:0}