訓練深度學習網路時候,出現Nan是什麼原因,怎麼才能避免?
在訓練深度學習的網路時候,迭代一定次數,會出現loss是nan,然後acc很快降低到了0.1,訓練也就無法繼續了。這個是什麼原因?有說法是「尺度不平衡的初始化」,這個是什麼意思?怎麼才能解決呢?
最近做了一組實驗,每次在固定的迭代次數段,都會loss突然變nan,導致acc驟降,慢慢變0。
於是找啊找啊找bug……
很難受,在意志力的堅持下,找到海枯石爛終於知道了!
loss突然變nan的原因,很可惜並不是這裡其他所有答主所說的「因為梯度爆炸」、「lr過大」、「不收斂」等等原因,而是因為training sample中出現了臟數據!
臟數據的出現導致我的logits計算出了0,0傳給 即nan。
所以我通過設置batch_size = 1,shuffle = False,一步一步地將sample定位到了所有可能的臟數據,刪掉。期間,刪了好幾個還依然會loss斷崖為nan,不甘心,一直定位一直刪。終於tm work out!
之所以會這樣,是因為我的實驗是實際業務上的真實數據,有實際經驗的就知道的,現實的數據非常之臟,基本上數據預處理佔據我80%的精力。
好懷念以前可以天真快樂的在open dataset上做task跑模型的時候,真是啥都不用管,專註模型演算法……
說明訓練不收斂了, 學習率太大,步子邁的太大導致梯度爆炸等都是有可能的,另外也有可能是網路的問題,網路結構設計的有問題。我現在的採用方式是: 1. 弱化場景,將你的樣本簡化,各個學習率等參數採用典型配置,比如10萬樣本都是同一張複製的,讓這個網路去擬合,如果有問題,則是網路的問題。否則則是各個參數的問題。 2. 如果是網路的問題,則通過不斷加大樣本的複雜度和調整網路(調整擬合能力)來改變。 3. 參數的微調,我個人感覺是在網路的擬合能力和樣本的複雜度匹配的情況下,就是可以train到一定水平,然後想進行進一步優化的時候採用。 4. 參數的微調,樓上說得幾個也算是一種思路吧,其他的靠自己去積累,另外將weights可視化也是一個細調起來可以用的方法,現在digits tf裡面都有相關的工具.
Not a Number,梯度的數值過大。,原因有很多,其他人回答的都很好。
跑飛了吧,數據太大了,已經超過了規定的極限--------------------------------------------------我是分割線--------------------------------loss出現Nan,說明你的loss已經發散了。下面是一點個人經驗,無理論指導,歡迎板磚。解決辦法:1、減小整體學習率。學習率比較大的時候,參數可能over shoot了,結果就是找不到極小值點。減小學習率可以讓參數朝著極值點前進。2、改變網路寬度。有可能是網路後面的層參數更新異常,增加後面層的寬度試試。3、增加網路層數。4、改變層的學習率。每個層都可以設置學習率,可以嘗試減小後面層的學習率試試。
是不是用了tanh?
梯度爆炸了吧。
我的解決辦法一般以下幾條:1、數據歸一化(減均值,除方差,或者加入normalization,例如BN、L2 norm等);2、更換參數初始化方法(對於CNN,一般用xavier或者msra的初始化方法);3、減小學習率、減小batch size;4、加入gradient clipping;在訓練深度神經網路的時候,出現NaN比較大的可能是因為學習速率過大,梯度值過大,產生梯度爆炸。
During experimentation, once the gradient value grows extremely large, it causes an overflow (i.e. NaN) which is easily detectable at runtime; this issue is called the Gradient Explosion Problem.
參考斯坦福CS 224D的lecture note,我們也可以找到一些解決方法:
1. 加入Gradient clipping:每當梯度達到一定的閾值,就把他們設置回一個小一些的數字。To solve the problem of exploding gradients, Thomas Mikolov first
Figure 5 visualizes the effect of gradient clipping. It shows the decision
introduced a simple heuristic solution that clips gradients to a small
number whenever they explode. That is, whenever they reach a certain
threshold, they are set back to a small number as shown in Algorithm
1.
surface of a small recurrent neural network with respect to its
W matrix and its bias terms, b. The model consists of a single unit
of recurrent neural network running through a small number of timesteps;
the solid arrows illustrate the training progress on each gradient
descent step. When the gradient descent model hits the high error wall
in the objective function, the gradient is pushed off to a far-away location
on the decision surface. The clipping model produces the dashed
line where it instead pulls back the error gradient to somewhere close
to the original gradient landscape.
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv+ 1e-10))
好吧我是來抖機靈的......
用的是交叉熵cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))的話,最後softmax層輸出y_conv的取值範圍在[0,1]頁就是說允許取0值,有log(0)出現很有可能出現nan啊,cross_entropy = -tf.reduce_mean(y_*tf.log(tf.clip_by_value(y_conv,1e-15,1.0)))在tensorflow里可以限定一下y_conv的取值範圍,別的框架不清楚。
我的一開始loss就是nan,然後準確率保持在0.1左右,請問樓主是怎麼解決的呀
梯度爆炸。。請使用一些歸一化
對於我的case, 試了所有別的方法後都不管用 也是果然在檢測輸入數據的時候發現某幾十萬行那裡發現了一行NAN,所以說第一步先檢測輸入數據里有沒有NAN,然後再試別的方法。
有一次的情況是,從訓練一開始loss就已經是nan,推測是網路設計的問題,加了BN做歸一化,解決了。
今天用keras訓練的時候也遇到了loss忽然降為nan的情況,最後發現是有一列特徵太不發散,做了標準化之後基本全為0的緣故,果斷刪掉該列,解決問題。
把每個batch的loss 計算方式從 tf.reduce_sum ,改為tf.reduce_mean 然後Nan的情況消失了,不知道為什麼?
推薦閱讀:
※[框架安裝趟雷指南]Ubuntu+1060+cuda+cudnn+Keras+TH+TF+MXnet
※細化 TensorFlow 的 Graph 有關知識
※進一步理解 TensorFlow 的 Graph 機制
※TensorFlow 訓練好模型參數的保存和恢復代碼
※TensorFlow學習筆記之二——安裝和運行
TAG:神經網路 | 深度學習DeepLearning | Caffe深度學習框架 | TensorFlow | Keras |