當前位置: 首頁>>技術問答>>正文


python – 深度學習Loss Nan的原因

在深度學習中Loss出現Nan的可能原因有哪些?

也許這個問題太籠統,但是誰能大致解釋下導致卷積神經網絡發散的原因呢?

問題細節:

我正在使用Tensorflow的iris_training模型以及一些我自己的數據,老是出現以下報錯:

ERROR:tensorflow:Model diverged with loss = NaN.

Traceback…

tensorflow.contrib.learn.python.learn.monitors.NanLossDuringTrainingError: NaN loss during training.

Traceback問題源於以下行:

 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")

我嘗試過調整優化器,將學習率設置為零,並且不使用優化器,然並卵。

 

最佳回答

常見的導致模型發散(Nan問題)原因:

  1. 學習率太高。損失是否開始增加然後發散到無窮大。
  2. 我對DNNClassifier不熟悉,但是我猜想它使用了分類交叉熵代價函數。這涉及獲取預測的對數,該對數隨著預測接近零而發散。這就是為什麽人們通常在預測中添加較小的ε值以防止這種差異。我猜測DNNClassifier可能會這樣做或使用tensorflow opp。
  3. 也可能存在其他數值穩定性問題,例如零除,在其中添加epsilon可能會有所幫助。一種不那麽明顯的情況是,如果在處理有限精度數時未適當簡化,則導數的平方根可能發散。我再次懷疑這是DNNClassifier的問題。
  4. 還可能是輸入數據有問題。嘗試對輸入數據調用assert not np.any(np.isnan(x)),以確保您沒有引入nan。還要確保所有目標值(樣本Label)均有效。最後,確保數據正確歸一化。您可能希望像素在[-1,1]而不是[0,255]範圍內。
  5. 另外,標簽(樣本Label)必須在損失函數值的域(範圍)中。例如,如果使用基於對數的損失函數,則所有標簽都必須是非負的。

 

次佳回答

如果您正在訓練交叉熵,則需要在輸出概率中添加一個小數,例如1e-8。

因為log(0)是負無窮大,所以當您的模型經過足夠的訓練後,輸出分布將非常偏斜,例如說我正在執行4類輸出,一開始我的概率類似下麵這樣:

0.25 0.25 0.25 0.25

但到最後,可能看起來像

1.0 0 0 0
如果對該分布進行交叉熵分解,問題就來了。解決方法是人為地在所有項中添加很小的數字,以防止出現這種情況。

 

第三種回答

調試NaN可能很棘手,尤其是在您擁有大型網絡的情況下。可以用 tf.add_check_numerics_ops()將ops添加到圖中,以聲明圖中的每個浮點張量不包含任何NaN值(默認情況下是不運行這些檢查的)。參考:tensorflow Nan調試


train_op = ...
check_op = tf.add_check_numerics_ops()

sess = tf.Session()
sess.run([train_op, check_op])  # Runs training and checks for NaNs

第四種回答

就我而言,設置遠距離整數LABEL時得到了NAN。即:

  • 標記[0..100]的訓練沒問題,
  • 標簽[0..100]加上一個附加標簽8000,然後我得到了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類。


loss nan

參考資料

 

本文由《純淨天空》出品。文章地址: https://vimsky.com/zh-tw/article/4341.html,未經允許,請勿轉載。