web-dev-qa-db-ja.com

回帰ネットワークのトレーニング時のNaN損失

260,000行と35列の「ワンホットエンコーディング」(すべて1と0)のデータマトリックスがあります。 Kerasを使用して、連続変数を予測する単純なニューラルネットワークをトレーニングしています。ネットワークを作成するコードは次のとおりです。

model = Sequential()
model.add(Dense(1024, input_shape=(n_train,)))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(1))

sgd = SGD(lr=0.01, nesterov=True);
#rms = RMSprop()
#model.compile(loss='categorical_crossentropy', optimizer=rms, metrics=['accuracy'])
model.compile(loss='mean_absolute_error', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_Epoch=3, verbose=1, validation_data=(X_test,Y_test), callbacks=[EarlyStopping(monitor='val_loss', patience=4)] )

ただし、トレーニングプロセスの間、損失はうまく減少しますが、2番目のエポックの中頃には、nanになります。

Train on 260000 samples, validate on 64905 samples
Epoch 1/3
260000/260000 [==============================] - 254s - loss: 16.2775 - val_loss:
 13.4925
Epoch 2/3
 88448/260000 [=========>....................] - ETA: 161s - loss: nan

RMSPropの代わりにSGDを使用しようとしましたが、tanhの代わりにreluを試してみました。私はより小さなモデル、つまり1つの隠れ層のみを使用して同じ問題を試しました(異なる点でnanになります)。ただし、少ない機能で動作します。つまり、列が5つしかない場合は、非常に良好な予測が得られます。何らかのオーバーフローがあるように見えますが、その理由は想像できません。損失はまったく不当に大きくありません。

Pythonバージョン2.7.11、Linuxマシンで実行、CPUのみ。 Theanoの最新バージョンでテストし、Nansも取得したので、Theano 0.8.2にアクセスして同じ問題が発生しました。 Kerasの最新バージョンには同じ問題があり、0.3.2バージョンにも問題があります。

46
The_Anomaly

出力が制限されていないため、ニューラルネットワークでの回帰は困難です。そのため、 爆発勾配の問題 (nanの原因となる可能性が高い)に特に陥りやすいです。

これまで、勾配を爆発させるための重要なソリューションの1つは学習率を下げることでしたが、Adamのようなパラメーターごとの適応学習率アルゴリズムの登場により、優れたパフォーマンスを得るために学習率を設定する必要がなくなりました。ニューラルネットワークの悪魔で、学習スケジュールを調整する方法を知らない限り、SGDを勢いで使用する理由はほとんどありません。

試してみることができるいくつかのことを次に示します。

  1. quantile normalizing または z scoring で出力を正規化します。厳密にするには、データセット全体ではなく、トレーニングデータでこの変換を計算します。たとえば、変位値の正規化では、例がトレーニングセットの60パーセンタイルにある場合、値は0.6になります。 (0パーセンタイルが-0.5、100パーセンタイルが+0.5になるように、変位値正規化値を0.5シフトダウンすることもできます)。

  2. ドロップアウト率を上げるか、重みにL1およびL2ペナルティを追加することにより、正規化を追加します。 L1の正則化は機能の選択に似ています。また、機能の数を5に減らすとパフォーマンスが向上すると述べたので、L1も同様です。

  3. それでも解決しない場合は、ネットワークのサイズを小さくしてください。これはパフォーマンスに悪影響を与える可能性があるため、必ずしも最良のアイデアとは限りませんが、入力フィーチャ(35)に比べて多数の第1層ニューロン(1024)があるため、役立つ場合があります。

  4. バッチサイズを32から128に増やします。128はかなり標準的なもので、最適化の安定性を高める可能性があります。

72
1''

1 "での答えは非常に良いです。しかし、すべての修正は問題を直接ではなく間接的に修正するようです。グラデーションクリッピングを使用することをお勧めします。

Kerasでは、clipnorm=1https://keras.io/optimizers/ を参照)を使用して、単に1を超えるノルムを持つすべてのグラデーションをクリップできます。

27
pir

以前同じ問題に直面しました。この質問と回答を検索して見つけます。上記のすべてのトリックは、ディープニューラルネットワークのトレーニングに重要です。私はそれらをすべて試してみましたが、それでもNANを受け取りました。

この質問もここにあります。 https://github.com/fchollet/keras/issues/2134 。著者の要約を次のように引用しました。

「今後この問題が発生する可能性がある他の人のためにアーカイブされるように、これを指摘したかったのです。私は損失関数を実行していましたが、それがトレーニングプロセスに深く入った後、突然ナンを返しました。 relus、オプティマイザ、損失関数、relusに応じたドロップアウト、ネットワークのサイズ、ネットワークの形状を確認しました。私はまだ損失を被っていましたが、最終的にはナンになり、かなりイライラしていました。

それから私は夜明けしました。入力が間違っている可能性があります。結局、私がCNNに渡した(そして平均正規化を行っていた)イメージの1つは0に他なりませんでした。平均を減算し、標準偏差で正規化したときにこのケースをチェックしていなかったため、最終的にはnan以外の模範行列になりました。正規化機能を修正すると、ネットワークは完全にトレーニングされます。」

上記の観点に同意します。入力はネットワークに敏感です。 私の場合、密度推定のログ値を入力として使用します。絶対値は非常に大きくなる可能性があり、数ステップの勾配の後にNaNになる場合があります。入力チェックが必要だと思います。まず、入力が含まれていないことを確認する必要がありますinclude-infまたはinf、または絶対値の非常に大きな数。

22
HenryZhao

私は非常によく似た問題に直面しました。

最初に試すことができるのは、ReluまたはTanhを使用する代わりに、アクティベーションをLeakyReLUに変更することです。その理由は、多くの場合、レイヤー内のノードの多くはアクティブ化がゼロであり、勾配もゼロであるため、バックプロポゲーションはこれらのノードの重みを更新しないためです。これは「dying ReLU」問題とも呼ばれます(詳細については、こちらを参照してください: https://datascience.stackexchange.com/questions/5706/what-is-the-dying-relu-problem-in -neural-networks )。

これを行うには、次を使用してLeakyReLUアクティベーションをインポートできます。

from keras.layers.advanced_activations import LeakyReLU

次のようにレイヤー内に組み込みます。

model.add(Dense(800,input_shape=(num_inputs,)))
model.add(LeakyReLU(alpha=0.1))

さらに、出力フィーチャ(予測しようとしている連続変数)が不均衡なデータセットであり、0が多すぎる可能性があります。この問題を解決する1つの方法は、スムージングを使用することです。これを行うには、この列のすべての値の分子に1を追加し、この列の各値を1 /(この列のすべての値の平均)で除算します。

これは基本的に、すべての値を0から0より大きい値にシフトします(非常に小さい場合もあります)。これにより、曲線が0を予測して損失を最小限に抑えることができます(最終的にNaNになります)。値が小さいほど、大きい値よりも大きな影響を受けますが、全体として、データセットの平均は同じままです。

7
Arnav

LSTMの使用で同じ問題に直面しました。問題は、標準化後にデータになんらかのnan値があるため、nan値がある場合は、標準化後に入力モデルデータを確認する必要があります。

print(np.any(np.isnan(X_test)))
print(np.any(np.isnan(y_test)))

これを解決するには、このようにStdに小さな値(0.000001)を追加します。

def standardize(train, test):


    mean = np.mean(train, axis=0)
    std = np.std(train, axis=0)+0.000001

    X_train = (train - mean) / std
    X_test = (test - mean) /std
    return X_train, X_test
2
javac

訓練が始まるとすぐに、最初のエポックでナンとして損失を被っていました。入力データからnasを削除するのと同じくらい簡単な解決策が私のために働いた(df.dropna())

これが同様の問題に遭遇した人の助けになることを願っています

2
Krithi07

このページや他の多くの提案をすべて試してみましたが、役に立ちませんでした。パンダでcsvファイルをインポートしてから、keras Tokenizerをテキスト入力で使用して、語彙とWordベクトル行列を作成しました。一部のCSVファイルがnanになったのに気付いた後、突然、ファイルのエンコードを調べて、asciiファイルがkerasで機能していないことに気付き、nanの損失と精度につながった0.0000e+00;ただし、-tf-8およびutf-16ファイルwereは機能していました!ブレークスルー。

テキスト分析を実行し、これらの提案を試してからnanの損失を取得している場合は、file -i {input}(linux)またはfile -I {input}(osx)を使用してファイルの種類を見つけてください。 ISO-8859-1またはus-asciiがある場合は、utf-8またはutf-16leに変換してみてください。後者は試していませんが、うまくいくと思います。うまくいけば、これは非常にイライラする人の助けになります!

1
Clay Coleman

ログロス、MAEおよびその他すべてがNAであるという問題がありました。データを調べてみたところ、NAの機能はほとんどありませんでした。 NAに近似値を代入し、問題を解決することができました。

1
Not_Dave

同じ問題がありました。多変量回帰問題にKerasを使用していました。後で気づいたのは、データセットの一部の値がnanであり、nanの損失につながったことです。私はコマンドを使用しました:

df=df.dropna()

そしてそれは私の問題を解決しました。

1
Kushagra Bhatia