TensorFlow中的Nan值的陷阱

轉自http://blog.sina.com.cn/s/blog_6ca0f5eb0102wr4j.html;如果涉及到版權請博主聯繫刪除

之前在TensorFlow中實現不同的神經網絡,作爲新手,發現經常會出現計算的loss中,出現Nan值的情況,總的來說,TensorFlow中出現Nan值的情況有兩種,一種是在loss中計算後得到了Nan值,另一種是在更新網絡權重等等數據的時候出現了Nan值,本文接下來,首先解決計算loss中得到Nan值的問題,隨後介紹更新網絡時,出現Nan值的情況。

Loss計算中出現Nan

在搜索以後,找到StackOverflow上找到大致的一個解決辦法(原文地址:https://stackoverflow.com/questions/33712178/tensorflow-nan-bug),大致的解決辦法就是,在出現Nan值的loss中一般是使用的TensorFlowlog函數,然後計算得到的Nan,一般是輸入的值中出現了負數值或者0值,在TensorFlow的官網上的教程中,使用其調試器調試Nan值的出現,也是查到了計算log的傳參爲0;而解決的辦法也很簡單,假設傳參給log的參數爲y,那麼在調用log前,進行一次數值剪切,修改調用如下:

loss = tf.log(tf.clip_by_value(y,1e-8,1.0))

這樣,y的最小值爲0的情況就被替換成了一個極小值,1e-8,這樣就不會出現Nan值了,StackOverflow上也給出了相同的解決方案。於是,我就採用了上述的解決方案對於log的參數進行數值限制,但是我更加複雜化了這個限制。

tf.clip_by_value這個函數,是將第一個參數,限制在第二、三個參數指定的範圍之內,使用這個函數的原意是要避免0值,並沒有限制最大值,因而我將限制的調用修改如下:

loss = tf.log(tf.clip_by_value(y,1e-8,tf.reduce_max(y)))

這樣就確保了對於y值的剪切,不會影響到其數值的上限。但是在實際的神經網絡中使用的時候,我發現這樣修改後,雖然loss的數值一直在變化,可是優化後的結果幾乎是保持不變的,這就存在問題了。

經過檢查,其實並不能這麼簡單的爲了持續訓練,而修改計算損失函數時的輸入值。這樣修改後,loss的數值很可能(存在0的話確定就是)假的數值,會對優化器優化的過程造成一定的影響,導致優化器並不能正常的工作。

要解決這個假的loss的方法很簡單,就是人爲的改造神經網絡,來控制輸出的結果,不會存在0。這就需要設計好最後一層輸出層的激活函數,每個激活函數都是存在值域的,詳情請見博客http://www.jianshu.com/p/ffd3e63f39ef,比如要給一個在(0,1)之間的輸出(不包含0),那麼顯然sigmoid是最好的選擇。不過需要注意的是,在TensorFlow中,tf.nn.sigmoid函數,在輸出的參數非常大,或者非常小的情況下,會給出邊界值1或者0的輸出,這就意味着,改造神經網絡的過程,並不只是最後一層輸出層的激活函數,你必須確保自己大致知道每一層的輸出的一個範圍,這樣才能徹底的解決Nan值的出現。

舉例說明就是TensorFlow的官網給的教程,其輸出層使用的是softmax激活函數,其數值在[0,1],這在設計的時候,基本就確定了會出現Nan值的情況,只是發生的時間罷了。

更新網絡時出現Nan

更新網絡中出現Nan值很難發現,但是一般調試程序的時候,會用summary去觀測權重等網絡中的值的更新,因而,此時出現Nan值的話,會報錯類似如下:

InvalidArgumentError (see above for traceback): Nan in summary histogram for: weight_1

這樣的情況,一般是由於優化器的學習率設置不當導致的,而且一般是學習率設置過高導致的,因而此時可以嘗試使用更小的學習率進行訓練來解決這樣的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章