spyder中调用不了tensorflow_TensorFlow 调试程序(一)

tfdbg 是 TensorFlow 的专用调试程序。借助该调试程序,您可以在训练和推理期间查看运行中 TensorFlow 图的内部结构和状态,由于 TensorFlow 的计算图模式,使用通用调试程序(如 Python 的 pdb)很难完成调试。

本指南重点介绍 tfdbg 的命令行界面 (CLI)。要了解如何使用 tfdbg 的图形界面 (GUI)(即 TensorBoard 调试程序插件),请访问相关 README 文件(https://github.com/tensorflow/tensorboard/blob/master/tensorboard/plugins/debugger/README.md)。

注意:TensorFlow 调试程序使用基于 curses 的文本界面。在 Mac OS X 上,ncurses 库是必需的,而且可以使用 brew install ncurses 进行安装。在 Windows 上,curses 并没有得到同样的支持,因此基于 readline 的界面可以与 tfdbg 配合使用(具体方法是使用 pip 安装 pyreadline)。如果您使用的是 Anaconda3,则可以使用 "C:\Program Files\Anaconda3\Scripts\pip.exe" install pyreadline 等命令进行安装。您可以在此处下载非官方 Windows curses 软件包,然后使用 pip install .whl 进行安装;不过,Windows 上的 curses 可能无法像 Linux 或 Mac 上的 curses 一样稳定地运行。

本教程展示了如何使用 tfdbg CLI 调试出现 nan 和 inf 的问题,这是 TensorFlow 模型开发期间经常出现的一种错误。下面的示例适用于使用低阶 TensorFlow Session API 的用户。本文档的后面部分介绍了如何将 tfdbg 与 TensorFlow 的更高阶 API(包括 tf.estimator、tf.keras / keras 和 tf.contrib.slim)结合使用。要观察此类问题,请在不使用调试程序的情况下运行以下命令(可在 此处 找到源代码 https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/debug/examples/debug_mnist.py):

python -m tensorflow.python.debug.examples.debug_mnist

此代码训练了一个简单的神经网络来识别 MNIST 数字图像。请注意,在完成第一个训练步之后,准确率略有提高,但之后停滞在较低(近机会)水平:

Accuracy at step 0: 0.1113
Accuracy at step 1: 0.3183
Accuracy at step 2: 0.098
Accuracy at step 3: 0.098
Accuracy at step 4: 0.098

您想知道哪里出了问题,怀疑训练图中的某些节点生成了错误数值(例如 inf 和 nan),因为这是导致此类训练失败的常见原因。我们可以使用 tfdbg 来调试此问题,并确定第一次出现此数字问题的确切图节点。

使用 tfdbg 封装 TensorFlow 会话

要向示例中的 tfdbg 添加支持,我们只需添加下列代码行,并使用调试程序封装容器封装会话对象。此代码已添加到 debug_mnist.py 中,因此您可以在命令行中使用 --debug 标记激活 tfdbg CLI。

# Let your BUILD target depend on "//tensorflow/python/debug:debug_py"
# (You don't need to worry about the BUILD dependency if you are using a pip
#  install of open-source TensorFlow.)
from tensorflow.python import debug as tf_debug
sess = tf_debug.LocalCLIDebugWrapperSession(sess)

此封装容器与会话具有相同的界面,因此启用调试时不需要对代码进行其他更改。该封装容器还提供其他功能,包括:

  • 在每次 Session.run() 调用前后调出 CLI,以便您控制执行情况和检查图的内部状态

  • 允许您为张量值注册特殊 filters,以便诊断问题

在本示例中,我们已经注册了一个名为 tfdbg.has_inf_or_nan 的张量过滤器,它仅仅确定任何中间张量(不是 Session.run() 调用的输入或输出、而是位于从输入到输出的路径中的张量)中是否存在任何 nan 或 inf 值。此过滤器可以确定是否存在 nan 和 inf,这是一种常见的用例,我们在 debug_data 模块中包含了此过滤器。

注意:您还可以自行编写自定义过滤器。要了解详情,请参阅 DebugDumpDir.find() 的 API 文档。

使用 tfdbg 调试模型训练

我们尝试再次训练模型,但这次添加 --debug 标记:

python -m tensorflow.python.debug.examples.debug_mnist --debug

调试封装容器会话会在将要执行第一次 Session.run() 调用时提示您,而屏幕上会显示关于获取的张量和 feed 字典的信息。

8586eff1e30f00e8ee10ba4d1e8b1016.png

这就是我们所说的 run-start CLI。它先列出对当前 Session.run 调用的 feed 和 fetch,然后再执行任何操作。

如果因屏幕尺寸太小而无法显示完整的消息内容,您可以调整屏幕大小。

使用 PageUp/PageDown/Home/End 键可以浏览屏幕上的输出。在大部分没有这些键的键盘上,使用 Fn + Up/Fn + Down/Fn + Right/Fn + Left 也可以。

在命令提示符处输入 run 命令(或只输入 r):

tfdbg> run

run 命令会让 tfdbg 一直执行,直到下一次 Session.run() 调用结束,而此调用会使用测试数据集计算模型的准确率。tfdbg 会扩展运行时图来转储所有中间张量。运行结束后,tfdbg 会在 run-end CLI 中显示所有转储的张量值。例如:

d67b5ffc4f3d80d3115550de2e8b5189.png

在执行 run 之后运行命令 lt 也可以获得此张量列表。

tfdbg CLI 常用命令

在 tfdbg> 提示符处尝试下列命令(参考 tensorflow/python/debug/examples/debug_mnist.py 中的代码):

9c50895b2776dd2a405d9a88896cba9f.png 756a45ef89335adba2493c5121ae4de0.png beb557df91df130d1d9249cb14dc851a.png ca0283fa58700a7890e8e1e700c46e7b.png c121ce381a84ecaffc9e77da94b58129.png 50ae2e875dcd9961e1c819e7e5337833.png dab73044417f027c865fed62a44ae06c.png

请注意,每次输入命令时,都会显示新的屏幕输出。这有点类似于浏览器中的网页。您可以通过点击 CLI 左上角附近的  文本箭头在这些屏幕之间导航。

tfdbg CLI 的其他功能

除了上面列出的命令外,tfdbg CLI 还提供了下列其他功能:

  • 要浏览之前的 tfdbg 命令,请输入几个字符,然后按向上或向下箭头键。tfdbg 会向您显示以这些字符开头的命令的历史记录

  • 要浏览屏幕输出的历史记录,请执行下列任一操作:

    使用 prev 和 next 命令

    点击屏幕左上角附近带下划线的  链接

  • 命令(和一些命令参数)的 Tab 补齐功能

  • 要将屏幕输出重定向到文件(而不是屏幕),请使用 bash 样式重定向结束命令。例如,以下命令会将 pt 命令的输出重定向到 /tmp/xent_value_slices.txt 文件:

tfdbg> pt cross_entropy/Log:0[:, 0:10] > /tmp/xent_value_slices.txt

查找 nan 和 inf

在第一个 Session.run() 调用中,没有出现存在问题的数值。您可以使用命令 run 或其简写形式 r 转到下一次运行。

提示:如果您反复输入 run 或 r,则将能够依序在 Session.run() 调用之间移动。

您还可以使用 -t 标记一次向前移动多个 Session.run() 调用,例如:

tfdbg> run -t 10

在每次 Session.run() 调用之后,您无需重复输入 run 并在 run-end 界面中手动搜索 nan 和 inf(例如,通过使用上表中显示的 pt 命令),而是可以使用以下命令让调试程序反复执行 Session.run() 调用(不在 run-start 或 run-end 提示符处停止),直到第一个 nan 或 inf 值出现在图中。这类似于一些程序式语言调试程序中的条件断点:

tfdbg> run -f has_inf_or_nan

注意:上述命令可正常运行,因为在创建封装会话时已为您注册了一个名为 has_inf_or_nan 的张量过滤器。此过滤器会检测 nan 和 inf(如前所述)。如果您已注册任何其他过滤器,则可以使用“run -f”让 tfdbg 一直运行,直到任何张量触发该过滤器(导致过滤器返回 True)为止。

def my_filter_callable(datum, tensor):
  # A filter that detects zero-valued scalars.
  return len(tensor.shape) == 0 and tensor == 0.0
sess.add_tensor_filter('my_filter', my_filter_callable)

然后在 tfdbg run-start 提示符处运行,直到您的过滤器被触发:

tfdbg> run -f my_filter

请参阅此 API 文档,详细了解与 add_tensor_filter() 搭配使用的谓词 Callable 的预期签名和返回值(https://tensorflow.google.cn/api_docs/python/tfdbg/DebugDumpDir?hl=zh-CN#find)。

1a72f6c3c04e7e2de4cb96aadf3e4613.png

如屏幕所示,在第一行中,has_inf_or_nan 过滤器在第四次 Session.run() 调用期间第一次被触发:Adam 优化器前向-后向训练通过了图。在本次运行中,36 个(共 95 个)中间张量包含 nan 或 inf 值。这些张量按时间先后顺序列出,具体时间戳显示在左侧。在列表顶部,您可以看到第一次出现错误数值的第一个张量:cross_entropy/Log:0。

要查看张量的值,请点击带下划线的张量名称 cross_entropy/Log:0 或输入等效命令:

tfdbg> pt cross_entropy/Log:0

向下滚动一点,您会发现一些分散的 inf 值。如果很难用肉眼找到出现 inf 和 nan 的地方,可以使用以下命令执行正则表达式搜索并突出显示输出:

tfdbg> /inf

或者:

tfdbg> /(inf|nan)

您还可以使用 -s 或 --numeric_summary 命令获取张量中的数值类型的快速摘要:

tfdbg> pt -s cross_entropy/Log:0

您可以从摘要中看到 cross_entropy/Log:0 张量的若干个元素(共 1000 个)都是 -inf(负无穷大)。

为什么会出现这些负无穷大的值?为了进一步进行调试,通过点击顶部带下划线的 node_info 菜单项或输入等效的 node_info (ni) 命令,显示有关节点 cross_entropy/Log 的更多信息:

tfdbg> ni cross_entropy/Log

3dec4ecb1a81bff3c482713beffef9a9.png

您可以看到,此节点的指令类型为 Log,输入为节点 Softmax。运行以下命令可进一步查看输入张量:

tfdbg> pt Softmax:0

检查输入张量中的值,并搜索其中是否存在零:

tfdbg> /0\.000

确实存在零。现在很明显,错误数值的根源是节点 cross_entropy/Log 取零的对数。要在 Python 源代码中找出导致错误的行,请使用 ni 命令的 -t 标记来显示节点构造的回溯:

tfdbg> ni -t cross_entropy/Log

如果您点击屏幕顶部的“node_info”,tfdbg 会自动显示节点构造的回溯。

从回溯中可以看到该操作是在以下行构建的 - debug_mnist.py:

diff = y_ * tf.log(y)

tfdbg 有一个可以轻松将张量和指令追溯到 Python 源文件中的行的功能。它可以用行创建的指令或张量注解 Python 文件的行。要使用此功能,只需点击 ni -t  命令的堆栈追踪输出中带下划线的行编号,或者使用 ps(或 print_source)命令,例如:ps /path/to/source.py。例如,以下屏幕截图显示了 ps 命令的输出。

eec20be00e0fe2ac9491d20dbfb5bca3.png

解决问题

要解决此问题,请修改 debug_mnist.py,将原始行:

diff = -(y_ * tf.log(y))

更改为 softmax 交叉熵的在数值上稳定的内置实现:

diff = tf.losses.softmax_cross_entropy(labels=y_, logits=logits)

用 --debug 标记重新运行,如下所示:

python -m tensorflow.python.debug.examples.debug_mnist --debug

在 tfdbg> 提示符处输入以下命令:

run -f has_inf_or_nan`

确认没有任何张量被标记为包含 nan 或 inf 值,并且准确率现在继续上升(而不是停滞不变)。成功!

更多 AI 相关阅读:

  • TensorFlow Lite 对象检测

  • 标贝科技:TensorFlow 框架提升语音合成效果

  • 使用 TensorFlow Model Analysis 提升模型质量

5c0749c2ee62da4af1f5c171ca8b8136.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值