24

我當時正在運行TensorFlow,並且碰巧產生NaN。我想知道它是什麼,但我不知道如何做到這一點。主要問題是,在「正常」程序程序中,我只是在執行操作之前編寫一個打印語句。 TensorFlow的問題是我無法做到這一點,因爲我首先聲明(或定義)圖形,因此向圖形定義添加打印語句無濟於事。是否有任何規則,建議,啓發式方法,追查可能導致NaN的原因?如何在TensorFlow中調試NaN值?


在這種情況下,我知道更準確地看,因爲我有以下哪一行:

Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance 
Z = tf.sqrt(Delta_tilde) 
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity) 
Z = tf.pow(Z, 2.0) 
A = tf.exp(Z) 

時,這條線是目前我有它,它返回NaN通過我的總結作家聲明。爲什麼是這樣?有沒有辦法可以至少探索Z在平方根之後的價值?


對於我張貼的具體的例子,我試圖tf.Print(0,Z)但沒有成功它印什麼。如在:

Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance 
Z = tf.sqrt(Delta_tilde) 
tf.Print(0,[Z]) # <-------- TF PRINT STATMENT 
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity) 
Z = tf.pow(Z, 2.0) 
A = tf.exp(Z) 

我其實不明白tf.Print應該做什麼。爲什麼需要兩個參數?如果我想打印1張張爲什麼我需要通過2張?對我來說似乎很奇怪。


我一直在尋找的功能tf.add_check_numerics_ops(),但它並沒有說如何使用它(加上文檔似乎不是超級有用)。有誰知道如何使用它?


由於我對解決數據問題的評論可能不好,因此我使用了標準MNIST。然而,我計算的是一個正數量(pair-wise eucledian distance),然後對其進行平方根。因此,我不會看到這些數據具體會成爲一個問題。

回答

5

看起來您可以在完成圖表後調用它。

check = tf.add_check_numerics_ops()

我認爲這將增加檢查所有浮點運算。然後在會話運行功能中,您可以添加檢查操作。

sess.run([check, ...])

+1

FYI該錯過在使用優化的一些OPS - https://github.com/tensorflow/tensorflow/issues/2288 –

12

有幾個原因,你可以得到一個南結果,往往是因爲過高的學習率,但很多其他的原因可能就像例如在輸入隊列損壞數據或0計算的日誌。

總之,帶打印調試象你所說的不能用一個簡單的打印完成(因爲這將導致只有在圖形內的張量信息的打印和不打印任何實際值)。

但是,如果您使用tf.print作爲bullet圖(tf.print)的操作,那麼當圖執行時,您將得到打印的實際值(並且觀察這些值以便調試和理解你的網絡的行爲)。

但是,你正在使用的打印語句不完全正確的方式。這是一個操作,所以你需要傳遞張量並請求一個結果張量,你需要在執行圖中稍後處理。否則,操作不會被執行,也不會發生打印。試試這個:

Z = tf.sqrt(Delta_tilde) 
Z = tf.Print(Z,[Z], message="my Z-values:") # <-------- TF PRINT STATMENT 
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity) 
Z = tf.pow(Z, 2.0) 
+3

爲什麼一個必須通過第一Z如果第二Z數據是?實質上,'tf.Print'的API是令人困惑的。爲什麼我們需要兩個輸入參數來打印一件事? – Pinocchio

+0

評估第一個張量Z時打印張量列表[Z]。有時候可能想打印出不同的東西。 – holdenlee

+0

這裏有一個小剪輯,我覺得有用的張量'x': 'DEBUGGING = False' 'x = x if not DEBUGGING else tf.Print(x,[x],'Value of x:') –

1

首先,你需要檢查你輸入的數據是否正確。在大多數情況下,這是原因。但並不總是,當然。

我通常使用Tensorboard來查看訓練時發生了什麼。所以,你可以看到每一步的值與

Z = tf.pow(Z, 2.0)  
summary_z = tf.scalar_summary('z', Z) 
#etc.. 
summary_merge = tf.merge_all_summaries() 
#on each desired step save: 
    summary_str = sess.run(summary_merge) 
    summary_writer.add_summary(summary_str, i) 

你也可以簡單的eval並打印當前值:

print(sess.run(Z)) 
+0

問題是它獲得NaN值,所以我的總結作者實際上退出了我的腳本,所以我無法看到它。你是否建議在可能導致NaN的操作之前寫入值? (可能在sqrt之前)另外,這是網絡的一部分,所以我在某些列車上調用了sess.run。我不能只是sess.run Z不幸(或者我不知道如何)。 – Pinocchio

+0

您可以運行一些操作 'op1_answer,op2_answer,opN_answer = sess.run([op1,op2,opN],feed_dict = {etc ..})' –

0

我曾經發現找出nans和infs可能發生的位置比糾正錯誤要困難得多。作爲補充@ SCAI的答案,我想在這裏補充一些要點:

調試模塊,您可以通過輸入:

from tensorflow.python import debug as tf_debug 

比任何打印好得多或斷言。

您只需通過改變你的包裝,你會添加調試功能:

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

你會提示一個命令行界面,然後輸入: run -f has_inf_or_nanlt -f has_inf_or_nan找到其中的NaN或infs是。第一個是發生災難的第一個地方。通過變量名稱可以追蹤代碼中的原點。

參考:https://developers.googleblog.com/2017/02/debug-tensorflow-models-with-tfdbg.html