1. ホーム
  2. python

[解決済み] 回帰学習時のNaNロス

2022-10-24 21:16:53

質問

私は26万行と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回目のエポックの途中で、ナンになるんです。

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バージョンでも同じ問題があります。

どのように解決するのですか?

ニューラルネットワークによる回帰は、出力が非束縛であるため、うまくいくのが難しく、特に 勾配が爆発する問題 (nansの原因と思われる)が発生します。

歴史的に、爆発する勾配に対する1つの重要な解決策は、学習率を下げることでした。しかし、Adamのようなパラメータごとの適応学習率アルゴリズムの出現により、もはや学習率を設定しなくても良いパフォーマンスを得ることができるようになったのです。 ニューラルネットワークの熱狂的なファンで、学習スケジュールを調整する方法を知らない限り、勢いのあるSGDを使用する理由はもうほとんどないのです。

以下は、あなたが試せる可能性のあることです。

  1. によって出力を正規化する。 分位正規化 または z スコアリング . 厳密には、この変換はデータセット全体ではなく、トレーニングデータに対して計算します。 例えば、分位正規化では、ある例がトレーニングセットの60パーセンタイルにある場合、その値は0.6になります。 (また、分位正規化した値を0.5ずつ下にシフトして、0パーセンタイルが-0.5、100パーセンタイルが+0.5となるようにすることも可能です)。

  2. ドロップアウト率を上げるか、重みにL1およびL2ペナルティを追加することで、正則化を追加します。 L1正則化は特徴選択と類似しており、特徴数を5個に減らすと良いパフォーマンスが得られるとのことなので、L1もありかもしれません。

  3. それでもだめなら、ネットワークのサイズを小さくします。 これは、パフォーマンスに悪影響を与える可能性があるため、常に最善のアイデアというわけではありませんが、あなたのケースでは、入力特徴 (35) に対して第一層のニューロン数が多い (1024) ので、役立つ可能性があります。

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