為什麼用tensorflow訓練網路,出現了loss=nan,accuracy總是一個固定值?

用tensorflow訓練網路,出現了loss=nan,accuracy總是一個固定值的情況,不管我用哪台電腦,如何訓練,測試集得到的accuracy都是一個固定值0.391071,loss=nan,如下圖:

輸出訓練每一個batch的loss和accuracy,發現是下圖這樣,我試著調整過learning rate,也列印了預處理後的數據,數據本身沒有問題,不知道問題到底出在哪裡了,已經抓頭髮好久了。。。頭髮少的工科女表示已瘋。。。不知是否有大神也碰到過類似情況?能給我指點一二。


最常見的原因是學習率太高。對於分類問題,學習率太高會導致模型「頑固」地認為某些數據屬於錯誤的類,而正確的類的概率為 0(實際是浮點數下溢),這樣用交叉熵就會算出無窮大的損失函數。一旦出現這種情況,無窮大對參數求導就會變成 NaN,之後整個網路的參數就都變成 NaN 了。

解決方法是調小學習率,甚至把學習率調成 0,看看問題是否仍然存在。若問題消失,那說明確實是學習率的問題。若問題仍存在,那說明剛剛初始化的網路就已經掛掉了,很可能是實現有錯誤。


其實需要更多信息的,比如如果有你的模型的代碼,是否可以提供最小化實現這個問題的代碼。提問三連。。

loss Nan有若干種問題:

  1. 學習率太高。所以如果有代碼我們可以看一看你的lr是多少
  2. loss函數用的什麼函數?對於分類問題,用categorical cross entropy
  3. 對於回歸問題,可能出現了除0 的計算,加一個很小的余項可能可以解決
  4. 數據本身,是否存在Nan,可以用numpy.any(numpy.isnan(x))檢查一下input和target
  5. target本身應該是能夠被loss函數計算的,比如sigmoid激活函數的target應該大於0,同樣的需要檢查數據集


按照你的描述,假設是一個分類問題的loss。如果你是自己實現的交叉熵損失函數,且直接按照公式實現 -[y * log(hat{y}) + (1 - y) * log(1 - hat{y})] ,那麼很有可能是計算sigmoid的時候exp(-x)溢出導致loss出現nan。所以要麼直接用tf官方的交叉熵函數,要麼按照tf官方交叉熵的寫法自己實現。

如果不是這個問題,那麼參考Maigo大神的建議重新修改學習率試試。


調參的時候有條首要的定律,尤其是對基於梯度下降訓練的模型,那就是:

Keep Calm and LOWER your LEARNING RATE.

先按照數量級等級降低(例如一次10倍降低)一般都可以解決NaN問題。

總之學習率降下去了再看其他參數。


提供一些小技巧,血淚教訓啊

1.在訓練的時候,整個網路隨機初始化,很容易出現nan,這時候需要把學習率調小,可以嘗試0.1,0.01,0.001,直到不出現nan為止,如果一直都有,那可能是網路實現問題。

2.學習率和網路的層數一般成反比,層數越多,學習率通常要減小

3.有時候可以先用較小的學習率訓練5000或以上次迭代,得到參數輸出,手動kill掉訓練,用前面的參數fine tune,這時候可以加大學習率,能更快收斂哦

4.如果用caffe訓練的話,你會看到沒輸出,但是gpu的利用率一直為0或很小,兄弟,已經nan了,只是因為你display那裡設置大了,導致無法顯示,設為1就可以看到了

5.有時候你可能只需要換一個隨機數種子,你發現就可以了,別問我為什麼知道 ,哭暈在廁所里了,偽科學吧


我遇到過一次loss出現NaN的問題,當時的原因是代碼寫錯了。代碼出錯的原因是結果輸出只有10個類別但是label中錯給了一個11。


下午解決一個TF loss = nan 的問題,原因是分類label數據處理有誤 有 -1 這樣的值存在,合理的值應該是[0, N)。而使用GPU做計算不會報這個具體的錯誤,CPU運行會報出了label值有-1這個錯誤信息,建議:

1)在CPU模型下運行,看看出錯信息;

2)使用clip norm防止梯度爆炸(之前優化RNN-CTC的時候遇到梯度爆炸導致loss = nan的問題)


nan,程序已經訓飛了。參數不合適,或者模型代碼有問題。


TensorFlow有專門的內置調試器(tfdbg)來幫助調試此類問題。詳細使用說明請見:

https://www.tensorflow.org/programmers_guide/debugger

tfdbg的具體工作原理是一個tf.Session的Wrapper:

from tensorflow.python import debug as tf_debug

# 建立原來的Session

sess = tf.Session()

# 用tfdbg的Wrapper包裹原來的Session對象:

sess = tf_debug.LocalCLIDebugWrapperSession(sess)

sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan)

# 以上為所有需要的代碼變動,其餘的代碼可以保留不變,因為包裹有的sess和原來的界面一致。

# 但是每次執行sess.run()的時候,自動進入調試器命令行環境。

sess.run(train_op, feed_dict=...)

在tfdbg命令行環境裡面,輸入如下命令,可以讓程序執行到inf或nan第一次出現。

tfdbg&> run -f has_inf_or_nan

一旦inf/nan出現,界面現實所有包含此類病態數值的張量,按照時間排序。所以第一個就

最有可能是最先出現inf/nan的節點。可以用node_info, list_inputs等命令進一步查看

節點的類型和輸入,來發現問題的緣由。


這個問題我在做驗證碼識別的時候也碰到過,主要看loss的定義,我當時用的是交叉熵,出現了nan就比較好理解了,加個很小的正數偏移就可以避免了。樓主可以貼下loss的定義


我目前也在經歷這種問題 acc上下浮動趨於穩定 準確率過低 我就有種感覺我的數據不好 不如題主貼上來模型代碼具體交流一下?


絕x是梯度爆了


1,輸入數據有問題,裡面有nan;2,層數太多或學習率太高梯度下降時造成dead neuron。


補充:當然只要加了batch normalization,下面的都不是問題!

1.如果是圖片,那麼得轉化為float 也就是/255.

2.relu和softmax兩層不要連著用,最好將relu改成tanh

3.學習率

4.參數初始化


可能原因很多。前面很多人提learning rate,但其實在保證模型以及loss正確的前提下才輪到learning rate,哦對,還有合理的初始化。我覺得先把learning rate調到一個較小的固定值按順序檢查這三項比較靠譜。

修改一下,對初學者來說,最可能的原因是連數據都沒做規整,featuremap很快就變很大,超出float32的範圍,變成nan。同理原來提到的參數初始化也同樣重要


今天遇到了過個,loss function出現無窮了。解決掉無窮就好了。


原因很多 可能梯度炸了


tf是很容易出nan的,如果題主願意提供源碼或許可以讓大家給出更多的建議。

一般來說,出問題的原因是sigmoid,log,div這些會算出無限大的op導致的;也有可能是模型本身數值不穩定,我有一次把文本中的數字直接傳到一個lstm裡面,它總是會nan。

現在tf出了tfdebug用來調試,之前的話也有peint或者傳出來到numpy進行分析。


前兩天經歷了一次樓主的情況, 梯度更新函數SGD沒有寫.................


NaN具有傳遞性。。。

訓練的時候,如果某個地方炸了或者發生了除零錯,在設備上是不會觸發中斷的。這個時候如果污染了你的參數,會導致一部分或者全部參數數值變成NaN。然後後面的batch就全是NaN了,然後這組模型的網路權重參數就廢了。。。


推薦閱讀:

如何訓練狗不撲人?
外國軍隊(比如美軍)的隊列訓練是什麼樣的?
如何制定抱石訓練計劃?
如何有效自己訓練 ACM?
手腕扭傷怎麼進行康復訓練?

TAG:訓練 | 梯度下降 | 深度學習DeepLearning | TensorFlow |