訓練深度學習網絡時候,出現Nan是什么原因,怎么才能避免?——我自己是因為data有nan的壞數據,clear下解決


Harick
from:https://www.zhihu.com/question/49346370
 
 
 

梯度爆炸了吧。

我的解決辦法一般以下幾條:
1、數據歸一化(減均值,除方差,或者加入normalization,例如BN、L2 norm等);
2、更換參數初始化方法(對於CNN,一般用xavier或者msra的初始化方法);
3、減小學習率、減小batch size;
4、加入gradient clipping;
 
 
 
說明訓練不收斂了, 學習率太大,步子邁的太大導致梯度爆炸等都是有可能的,另外也有可能是網絡的問題,網絡結構設計的有問題。
我現在的采用方式是:
1. 弱化場景,將你的樣本簡化,各個學習率等參數采用典型配置,比如10萬樣本都是同一張復制的,讓這個網絡去擬合,如果有問題,則是網絡的問題。否則則是各個參數的問題。
2. 如果是網絡的問題,則通過不斷加大樣本的復雜度和調整網絡(調整擬合能力)來改變。
3. 參數的微調,我個人感覺是在網絡的擬合能力和樣本的復雜度匹配的情況下,就是可以train到一定水平,然后想進行進一步優化的時候采用。
4. 參數的微調,樓上說得幾個也算是一種思路吧,其他的靠自己去積累,另外將weights可視化也是一個細調起來可以用的方法,現在digits tf里面都有相關的工具.
 
 
 

最近做了一組實驗,每次在固定的迭代次數段,都會loss突然變nan,導致acc驟降,慢慢變0。

於是找啊找啊找bug……

很難受,在意志力的堅持下,找到海枯石爛終於知道了!

loss突然變nan的原因,很可惜並不是這里其他所有答主所說的“因為梯度爆炸”、“lr過大”、“不收斂”等等原因,而是因為training sample中出現了臟數據

臟數據的出現導致我的logits計算出了0,0傳給 log(x|x=0) \rightarrow ∞, 即nan。

所以我通過設置batch_size = 1,shuffle = False,一步一步地將sample定位到了所有可能的臟數據,刪掉。期間,刪了好幾個還依然會loss斷崖為nan,不甘心,一直定位一直刪。終於tm work out!

之所以會這樣,是因為我的實驗是實際業務上的真實數據,有實際經驗的就知道的,現實的數據非常之臟,基本上數據預處理占據我80%的精力。

好懷念以前可以天真快樂的在open dataset上做task跑模型的時候,真是啥都不用管,專注模型算法……

 
 
 
在訓練深度神經網絡的時候,出現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:每當梯度達到一定的閾值,就把他們設置回一個小一些的數字。
\frac{\partial E}{\partial W} \rightarrow g
if \left| \left| g \right| \right|  \geq threshold then
\frac{threshlod}{\left| \left|  g \right| \right| }g\rightarrow g
endif
2. 調整學習速率。學習速率過大會導致不能正常收斂,因此可以把學習速率適當調小一些。
3. 調整深度神經網絡的結構。
To solve the problem of exploding gradients, Thomas Mikolov first 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.
Figure 5 visualizes the effect of gradient clipping. It shows the decision 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))的話,最后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的取值范圍,別的框架不清楚。

 
 
 
是不是用了tanh?
 
 

相信很多人都遇到過訓練一個deep model的過程中,loss突然變成了NaN。在這里對這個問題做一個總結。

一般來說,出現NaN有以下幾種情況:

1.如果在迭代的100輪以內,出現NaN,一般情況下的原因是因為你的學習率過高,需要降低學習率。可以不斷降低學習率直至不出現NaN為止,一般來說低於現有學習率1-10倍即可。

2.如果當前的網絡是類似於RNN的循環神經網絡的話,出現NaN可能是因為梯度爆炸的原因,一個有效的方式是增加“gradient clipping”(梯度截斷來解決)

3.可能用0作為了除數;

4.可能0或者負數作為自然對數

5.需要計算loss的數組越界(尤其是自己,自定義了一個新的網絡,可能出現這種情況)

6.在某些涉及指數計算,可能最后算得值為INF(無窮)(比如不做其他處理的softmax中分子分母需要計算exp(x),值過大,最后可能為INF/INF,得到NaN,此時你要確認你使用的softmax中在計算exp(x)做了相關處理(比如減去最大值等等))

參考:
http://russellsstewart.com/notes/0.html

 

tensorflow訓練中出現nan問題

原創 2017年06月24日 14:16:22
 

        深度學習中對於網絡的訓練是參數更新的過程,需要注意一種情況就是輸入數據未做歸一化時,如果前向傳播結果已經是[0,0,0,1,0,0,0,0]這種形式,而真實結果是[1,0,0,0,0,0,0,0,0],此時由於得出的結論不懼有概率性,而是錯誤的估計值,此時反向傳播會使得權重和偏置值變的無窮大,導致數據溢出,也就出現了nan的問題。

解決辦法:

1、對輸入數據進行歸一化處理,如將輸入的圖片數據除以255將其轉化成0-1之間的數據;

2、對於層數較多的情況,各層都做batch_nomorlization;

3、對設置Weights權重使用tf.truncated_normal(0, 0.01, [3,3,1,64])生成,同時值的均值為0,方差要小一些;

4、激活函數可以使用tanh;

5、減小學習率lr。

from:http://blog.csdn.net/fireflychh/article/details/73691373

 

 

 

使用caffe訓練時Loss變為nan的原因

 

梯度爆炸

原因:梯度變得非常大,使得學習過程難以繼續

現象:觀察log,注意每一輪迭代后的loss。loss隨着每輪迭代越來越大,最終超過了浮點型表示的范圍,就變成了NaN。

措施:
1. 減小solver.prototxt中的base_lr,至少減小一個數量級。如果有多個loss layer,需要找出哪個損失層導致了梯度爆炸,並在train_val.prototxt中減小該層的loss_weight,而非是減小通用的base_lr。
2. 設置clip gradient,用於限制過大的diff

不當的損失函數

原因:有時候損失層中loss的計算可能導致NaN的出現。比如,給InfogainLoss層(信息熵損失)輸入沒有歸一化的值,使用帶有bug的自定義損失層等等。

現象:觀測訓練產生的log時一開始並不能看到異常,loss也在逐步的降低,但突然之間NaN就出現了。

措施:看看你是否能重現這個錯誤,在loss layer中加入一些輸出以進行調試。

示例:有一次我使用的loss歸一化了batch中label錯誤的次數。如果某個label從未在batch中出現過,loss就會變成NaN。在這種情況下,可以用足夠大的batch來盡量避免這個錯誤。

不當的輸入

原因:輸入中就含有NaN。

現象:每當學習的過程中碰到這個錯誤的輸入,就會變成NaN。觀察log的時候也許不能察覺任何異常,loss逐步的降低,但突然間就變成NaN了。

措施:重整你的數據集,確保訓練集和驗證集里面沒有損壞的圖片。調試中你可以使用一個簡單的網絡來讀取輸入層,有一個缺省的loss,並過一遍所有輸入,如果其中有錯誤的輸入,這個缺省的層也會產生NaN。

案例:有一次公司需要訓練一個模型,把標注好的圖片放在了七牛上,拉下來的時候發生了dns劫持,有一張圖片被換成了淘寶的購物二維碼,且這個二維碼格式與原圖的格式不符合,因此成為了一張“損壞”圖片。每次訓練遇到這個圖片的時候就會產生NaN。良好的習慣是,你有一個檢測性的網絡,每次訓練目標網絡之前把所有的樣本在這個檢測性的網絡里面過一遍,去掉非法值。

池化層中步長比核的尺寸大

如下例所示,當池化層中stride > kernel的時候會在y中產生NaN

    layer {
      name: "faulty_pooling"
      type: "Pooling"
      bottom: "x"
      top: "y"
      pooling_param {
      pool: AVE
      stride: 5
      kernel: 3
      }
    }

致謝

http://stackoverflow.com/questions/33962226/common-causes-of-NaNs-during-training

 

from:http://blog.csdn.net/huangynn/article/details/52947894

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM