おそらく一般的な質問ですが、だれでも畳み込みニューラルネットワークが発散する原因を説明できますか?
詳細:
Tensorflowのiris_trainingモデルを自分のデータの一部で使用していますが、
エラー:tensorflow:モデルは損失= NaNで発散しました。
トレースバック...
tensorflow.contrib.learn.python.learn.monitors.NanLossDuringTrainingError:トレーニング中のNaN損失。
トレースバックは次の行から始まりました。
tf.contrib.learn.DNNClassifier(feature_columns=feature_columns,
hidden_units=[300, 300, 300],
#optimizer=tf.train.ProximalAdagradOptimizer(learning_rate=0.001, l1_regularization_strength=0.00001),
n_classes=11,
model_dir="/tmp/iris_model")
学習率にゼロを使用し、オプティマイザーを使用せずに、オプティマイザーを調整しようとしました。ネットワーク層、データサイズなどについての洞察を歓迎します。
モデルを分岐させるのを見たことがたくさんあります。
学習率が高すぎます。損失が増加し始め、その後無限に発散する場合、これが当てはまるかどうかをよく知ることができます。
私はDNNClassifierに精通していませんが、カテゴリーのクロスエントロピーコスト関数を使用していると推測しています。これには、予測がゼロに近づくにつれて分岐する予測のログを取ることが含まれます。このため、人々は通常、予測に小さなイプシロン値を追加して、この発散を防ぎます。 DNNClassifierはおそらくこれを行うか、それのためにテンソルフローoppを使用していると推測しています。おそらく問題ではありません。
イプシロンを追加すると役立つゼロ除算など、他の数値安定性の問題が存在する可能性があります。微分の平方根が、有限精度の数値を扱うときに適切に単純化されていないと発散する可能性がある場合は、もう少しわかりにくいものです。繰り返しますが、これがDNNClassifierの場合の問題だとは思いません。
入力データに問題がある可能性があります。入力データでassert not np.any(np.isnan(x))
を呼び出して、nanを導入していないことを確認してください。また、すべてのターゲット値が有効であることを確認してください。最後に、データが適切に正規化されていることを確認してください。おそらく、ピクセルを[0、255]ではなく[-1、1]の範囲にしたいでしょう。
ラベルは損失関数の領域内にある必要があるため、対数ベースの損失関数を使用する場合、すべてのラベルは非負でなければなりません(evan puおよび以下のコメントで説明されているように)。
クロスエントロピーのトレーニングをしている場合、出力確率に1e-8のような小さな数値を追加します。
Log(0)は負の無限大であるため、モデルが十分にトレーニングされると、出力分布は非常に歪んでしまいます。たとえば、4クラスの出力を行う場合、最初は確率が次のようになります。
0.25 0.25 0.25 0.25
しかし、最後に向かって確率はおそらく次のようになります
1.0 0 0 0
そして、この分布のクロスエントロピーを取り、すべてが爆発します。修正は、これを防ぐためにすべての用語に少数を人為的に追加することです。
私の場合、離れた整数のLABELを設定するとNANになりました。すなわち:
したがって、非常に離れたラベルを使用しないでください。
編集次の簡単なコードで効果を確認できます。
from keras.models import Sequential
from keras.layers import Dense, Activation
import numpy as np
X=np.random.random(size=(20,5))
y=np.random.randint(0,high=5, size=(20,1))
model = Sequential([
Dense(10, input_dim=X.shape[1]),
Activation('relu'),
Dense(5),
Activation('softmax')
])
model.compile(optimizer = "Adam", loss = "sparse_categorical_crossentropy", metrics = ["accuracy"] )
print('fit model with labels in range 0..5')
history = model.fit(X, y, epochs= 5 )
X = np.vstack( (X, np.random.random(size=(1,5))))
y = np.vstack( ( y, [[8000]]))
print('fit model with labels in range 0..5 plus 8000')
history = model.fit(X, y, epochs= 5 )
結果は、ラベル8000を追加した後のNANを示しています。
fit model with labels in range 0..5
Epoch 1/5
20/20 [==============================] - 0s 25ms/step - loss: 1.8345 - acc: 0.1500
Epoch 2/5
20/20 [==============================] - 0s 150us/step - loss: 1.8312 - acc: 0.1500
Epoch 3/5
20/20 [==============================] - 0s 151us/step - loss: 1.8273 - acc: 0.1500
Epoch 4/5
20/20 [==============================] - 0s 198us/step - loss: 1.8233 - acc: 0.1500
Epoch 5/5
20/20 [==============================] - 0s 151us/step - loss: 1.8192 - acc: 0.1500
fit model with labels in range 0..5 plus 8000
Epoch 1/5
21/21 [==============================] - 0s 142us/step - loss: nan - acc: 0.1429
Epoch 2/5
21/21 [==============================] - 0s 238us/step - loss: nan - acc: 0.2381
Epoch 3/5
21/21 [==============================] - 0s 191us/step - loss: nan - acc: 0.2381
Epoch 4/5
21/21 [==============================] - 0s 191us/step - loss: nan - acc: 0.2381
Epoch 5/5
21/21 [==============================] - 0s 188us/step - loss: nan - acc: 0.2381
ターゲットとして整数を使用する場合は、整数が0で対称になっていないことを確認してください。
つまり、クラス-1、0、1を使用しないでください。代わりに0、1、2を使用します。
エラーに関する詳細情報を収集し、最初の数回の繰り返しでエラーが発生する場合は、CPU専用モード(GPUなし)で実験を実行することをお勧めします。エラーメッセージはより具体的になります。
正則化が役立ちます。分類子の場合、それがバイナリ分類子であろうとマルチクラス分類子であろうと、アクティビティの正規化の良いケースがあります。リグレッサーの場合、カーネルの正規化がより適切な場合があります。