Pin*_*hio 45 python machine-learning neural-network conv-neural-network tensorflow
我正在运行TensorFlow,而我碰巧有一些产生NaN的东西.我想知道它是什么,但我不知道该怎么做.主要问题是在"正常"程序程序中,我只是在执行操作之前编写一个print语句.TensorFlow的问题在于我不能这样做,因为我首先声明(或定义)图形,因此向图形定义添加print语句没有帮助.是否有任何规则,建议,启发式方法,以及追踪可能导致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)
Run Code Online (Sandbox Code Playgroud)
当这一行存在时,我知道它返回由我的摘要编写者声明的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)
Run Code Online (Sandbox Code Playgroud)
我实际上不明白tf.Print
应该做什么.为什么需要两个参数?如果我想打印1张张,为什么我需要传递2?对我来说似乎很奇怪.
我正在查看函数tf.add_check_numerics_ops()但它没有说明如何使用它(加上文档似乎没有超级帮助).有谁知道如何使用它?
由于我对评论数据的评论可能不好,我使用的是标准的MNIST.但是,我正在计算一个积极的数量(成对的eucledian距离)然后平方根.因此,我不会看到数据具体如何成为一个问题.
Phi*_*ock 23
有几个原因为什么你可以获得NaN结果,通常是因为学习率太高,但还有很多其他原因,例如输入队列中的损坏数据或0计算日志.
无论如何,用你所描述的打印调试不能通过简单的打印来完成(因为这只会导致在图形内打印张量信息而不打印任何实际值).
但是,如果使用tf.print作为构建图形的操作(tf.print),那么当图形执行时,您将获得打印的实际值(并且观察这些值以调试和理解行为是一个很好的练习你的网).
但是,您使用print-statement并不完全正确.这是一个op,所以你需要传递一个张量并请求你需要在执行图中使用的结果张量.否则,op将不会被执行并且不会发生打印.试试这个:
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)
Run Code Online (Sandbox Code Playgroud)
Ler*_*ang 11
我曾经发现,精确定位nan和infs的位置要比修复bug困难得多。作为@scai答案的补充,我想在这里补充几点:
您可以通过以下方式导入调试模块:
from tensorflow.python import debug as tf_debug
Run Code Online (Sandbox Code Playgroud)
比任何印刷品或断言要好得多。
您可以通过以下方式更改会话的包装器来添加调试功能:
sess = tf_debug.LocalCLIDebugWrapperSession(sess)
sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan)
Run Code Online (Sandbox Code Playgroud)
然后,您将提示命令行界面,然后输入:
run -f has_inf_or_nan
并lt -f has_inf_or_nan
查找nans或infs的位置。第一个是发生灾难的第一个地方。通过变量名,您可以跟踪代码中的原点。
参考:https : //developers.googleblog.com/2017/02/debug-tensorflow-models-with-tfdbg.html
看起来你可以在完成图表后调用它.
check = tf.add_check_numerics_ops()
我认为这将添加所有浮点运算的检查.然后在会话运行功能中,您可以添加检查操作.
sess.run([check, ...])
从版本0.12开始,TensorFlow附带一个名为的内置调试器tfdbg
.它优化了调试此类错误数值问题(如inf
和nan
)的工作流程.文档位于:https:
//www.tensorflow.org/programmers_guide/debugger
小智 5
首先,您需要检查您输入的数据是否正确。在大多数情况下,这就是原因。但并非总是如此,当然。
我通常使用 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)
Run Code Online (Sandbox Code Playgroud)
您也可以简单地评估并打印当前值:
print(sess.run(Z))
Run Code Online (Sandbox Code Playgroud)
对于 TensorFlow 2,将一些注入x=tf.debugging.check_numerics(x,'x is nan')
到您的代码中。InvalidArgument
如果x
有任何不是数字 (NaN) 或无穷大 (Inf) 的值,它们将抛出错误。
哦,对于下一个在寻找 TF2 NaN 问题时发现这个问题的人,我的情况证明是一个爆炸梯度。梯度本身达到了 1e+20,这还不是 NaN,但是将其添加到变量中却变得太大了。我所做的诊断是
gradients = tape.gradient(loss, training_variables)
for g,v in zip(gradients, training_variables):
tf.print(v.name, tf.reduce_max(g))
optimizer.apply_gradients(zip(gradients, training_variables))
Run Code Online (Sandbox Code Playgroud)
这揭示了过大的数字。在 CPU 上运行完全相同的网络运行良好,但在我工作站的 GTX 1080 TI 上却失败了,因此导致 CUDA 数值稳定性问题可能是根本原因。但由于它只是偶尔发生,我通过以下方式对整个事情进行了录音:
gradients = tape.gradient(loss, training_variables)
gradients = [tf.clip_by_norm(g, 10.0) for g in gradients]
optimizer.apply_gradients(zip(gradients, training_variables))
Run Code Online (Sandbox Code Playgroud)
这只会将爆炸梯度剪辑到一个合理的值。对于梯度始终很高的网络,这无济于事,但由于幅度只是偶尔高,这解决了问题,现在网络在 GPU 上也能很好地训练。
归档时间: |
|
查看次数: |
18263 次 |
最近记录: |