如何在TensorFlow中调试NaN值?
conv-neural-network
machine-learning
neural-network
python
5
0

我正在运行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。但是,我正在计算一个正数(成对的欧氏距离),然后平方根。因此,我看不到具体的数据将是什么问题。

参考资料:
Stack Overflow
收藏
评论
共 5 个回答
高赞 时间 活跃

完成绘制图形后,您似乎可以调用它。

check = tf.add_check_numerics_ops()

我认为这将为所有浮点运算添加检查。然后,在会话运行功能中,您可以添加检查操作。

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

收藏
评论

从版本0.12开始,TensorFlow随附了一个名为tfdbg的内置调试器。它优化了调试此类不良数值问题(例如infnan )的工作流程。该文档位于: https : //www.tensorflow.org/programmers_guide/debugger

收藏
评论

为什么可以得到NaN结果有两个原因,通常是由于学习率太高,但是还有许多其他原因也是可能的,例如输入队列中的数据损坏或计算记录为0。

无论如何,使用您描述的打印调试无法通过简单的打印完成(因为这只会导致在图形内部打印张量信息,而不会打印任何实际值)。

但是,如果将tf.print用作构建图形( 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)
收藏
评论

我曾经发现,精确定位nan和infs的位置要比修复bug困难得多。作为@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查找lt -f has_inf_or_nan或inf的位置。第一个是发生灾难的第一个地方。通过变量名,您可以跟踪代码中的原点。

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

收藏
评论

首先,您需要检查输入数据是否正确。在大多数情况下,这就是原因。当然,并非总是如此。

我通常使用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)

您也可以简单地评估并打印当前值:

 print(sess.run(Z))
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号