页面树结构

2017-11-09 ApacheCN 开源组织,第二期邀请成员活动,一起走的更远 : http://www.apachecn.org/member/209.html


MachineLearning 优酷地址 : http://i.youku.com/apachecn

转至元数据结尾
转至元数据起始

(实验)

TensorFlow调试器(tfdbg)是TensorFlow的专用调试器。它提供了运行TensorFlow图的内部结构和状态的可见性。从这种可见性获得的洞察力应该有助于在训练和推理期间调试各种类型的模型错误。

本教程将展示tfdbg命令行界面(CLI)的功能,重点是如何调试TensorFlow模型开发中经常遇到的一种错误:导致培训失败的不良数值(nans和infs)。

观察此类问题,请运行以下代码,而无需调试器:

python -m tensorflow.python.debug.examples.debug_mnist
该代码训练一个简单的NN用于MNIST数字图像识别。请注意,准确度在第一个训练步骤后稍微增加,但随后停留在低(近机会)水平:

抓住你的头,你怀疑训练图中的某些节点产生了不正确的数值,如infs和nans。TensorFlow的计算图模式使用Python等通用调试器调试这种模型内部状态是不寻常的pdb。 tfdbg专门诊断这些类型的问题,并精确定位问题第一次出现的确切节点。

 

用tfdbg包装TensorFlow会话

为了在我们的示例中添加对tfdbg的支持,我们只需要添加以下三行代码,当--debug提供标志时,它将包含调用器包装器的Session对象包起来:

# 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)
sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan)
此包装器具有与Session相同的界面,因此启用调试不需要对代码进行任何其他更改。但是包装器提供了额外的功能,包括:
  • 在每次run()调用之前和之后启动基于终端的用户界面(UI) ,让您控制执行并检查图形的内部状态。
  • 允许您为张量值注册特殊的“过滤器”,以便于诊断问题。

在这个例子中,我们正在注册称为张量滤波器 tfdbg.has_inf_or_nan,其简单地确定是否有任何naninf在图形的任何中间张量的值。(这个过滤器是我们与debug_data 模块一起运送的常见的用例 )

def has_inf_or_nan(datum, tensor):
  return np.any(np.isnan(tensor)) or np.any(np.isinf(tensor))
提示:您还可以编写自己的自定义过滤器。请参阅API文档 的DebugDumpDir.find()附加信息。

 

使用tfdbg调试模型训练

让我们尝试训练模型再次启用调试。从上面执行命令,此时加--debug标志:

python -m tensorflow.python.debug.examples.debug_mnist --debug
调试包装器会话将在您即将执行第一次run()调用时提示您,并提供有关 获取的张量和馈送字典显示在屏幕上的信息。

这就是我们所说的run-start UI。如果屏幕尺寸太小,无法完整显示消息的内容,您可以调整其大小或使用PageUp / PageDown / Home / End键导航屏幕输出。

如屏幕输出所示,第一次run()调用使用测试数据集计算精度,即图形上的向前传递。您可以输入命令run(或其缩写r)启动run()呼叫。在支持鼠标事件的终端run上,您可以点击屏幕左上角的下划线继续。

这将在run()呼叫结束后立即启动另一个屏幕,这将显示所有倾倒的中间张量。(这些张量也可以通过执行命令lt后获得run)。这被称为 run-end UI

tfdbg CLI常用命令

tfdbg>提示符下尝试以下命令(引用代码 tensorflow/python/debug/examples/debug_mnist.py):

命令示例说明
pt hidden/Relu:0打印张量的值hidden/Relu:0
pt hidden/Relu:0[0:50,:] hidden/Relu:0使用numpy -style阵列切片打印张量的子阵列。
pt hidden/Relu:0[0:50,:] -a对于像这样的大张量,打印其整体的价值 - 即不使用任何省略号。可能需要很长时间的大张力。
pt hidden/Relu:0[0:10,:] -a -r [1,inf]使用-r标志突出显示落入指定数值范围的元素。多个范围可以结合使用,例如。-r [[-inf,-1],[1,inf]] 
@[10,0] 要么 @10,0导航到正在显示的张量中的[10,0]。
/inf使用正则表达式搜索屏幕输出inf并突出显示任何匹配项。
/滚动到与搜索到的正则表达式匹配的下一行(如果有)。
ni -a hidden/Relu显示有关节点的信息hidden/Relu,包括节点属性。
ni -t hidden/Relu显示节点结构的堆栈跟踪hidden/Relu
li -r hidden/Relu:0列出节点的输入hidden/Relu,递归 - 即输入树。
lo -r hidden/Relu:0列出节点hidden/Relu输出的收件人,递归(即输出收件人树)。
lt -n softmax.*列出名称与正则表达式模式匹配的所有转储张量。softmax.* 
lt -t MatMul列出节点类型为的所有倾倒张量MatMul
ps /path/to/source.py打印Python源文件source.py,并分别在每个文件中创建的ops注释行。
ps -t /path/to/source.py与上述命令相同,但使用转储式传感器代替操作执行注释。
ps -b 30 /path/to/source.py从第30行开始注释source.py。
run_info 要么 ri显示有关当前运行的信息,包括提取和Feed。
help打印一般帮助信息,列出所有可用的tfdbg命令及其标志。
help lt打印lt命令的帮助信息。

在这第一个run()电话中,碰巧没有问题的数值。您可以使用命令run或其速记进入下一个运行r

提示:如果您输入runr重复输入,您将能够以run()顺序的方式移动 通话。

您也可以使用-t标志一次移动多个run()通话,例如:

tfdbg> run -t 10

在每次调用之后,run不用重复输入并手动搜索运行结果UI中的nans和 infrun(),您可以使用以下命令让调试器重复执行run()调用,而不停止在运行启动或运行结束提示符,直到第一个naninf值显示在图表中。这类似于条件断点在一些程序语言的调试器:

tfdbg> run -f has_inf_or_nan

注意:这是因为我们以前已经为nans和infs 注册过滤器has_inf_or_nan(如前所述)。如果您已经注册了任何其他过滤器,您可以让tfdbg运行,直到任何张量也通过该过滤器,例如,

# In python code:
sess
.add_tensor_filter('my_filter', my_filter_callable)

# Run at tfdbg run-start prompt:
tfdbg
> run -f my_filter

输入后run -f has_inf_or_nan,您将看到带有红色标题行的以下屏幕,指示 tfdbg在run()通过指定过滤器的中间张量调用生成后立即停止has_inf_or_nan

如屏幕显示所示,has_inf_or_nan过滤器在第四次run()调用期间首先通过:Adam优化器 向前 - 向后训练图表。在这次运行中,36个(总共95个)中间张量包含naninf值。这些张量按时间顺序列出,其时间戳显示在左侧。在列表的顶部,你可以在其中看到不好的数值首次浮出水面第一张:cross_entropy/Log:0

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

tfdbg> pt cross_entropy/Log:0
向下滚动一点,你会注意到一些分散的inf值。如果实际inf并且nan难以察觉,可以使用以下命令执行正则表达式搜索并突出显示输出:
tfdbg> /inf
或者,或者:
tfdbg> /(inf|nan)
为什么这些无限出现?要进一步调试,请cross_entropy/Log通过单击node_info顶部的下划线菜单项或输入等效命令来显示有关节点的更多信息:
tfdbg> ni cross_entropy/Log

您可以看到该节点具有op类型Log ,并且其输入是节点softmax/Softmax。运行以下命令,仔细观察输入张量:

tfdbg> pt softmax/Softmax:0
检查输入张量中的值,并搜索是否有零:
tfdbg> /0\.000
确实有零。现在很清楚,不良数值的起源是cross_entropy/Log采取零日志的节点。要了解Python源代码中的罪魁祸首,请使用-tni命令的标志来显示节点结构的追溯:
tfdbg> ni -t cross_entropy/Log
-t默认情况下使用该标志,如果您使用屏幕顶部的可点击“node_info”菜单项。

从追溯中,您可以看到op是围绕第106行构建的 debug_mnist.py

diff = y_ * tf.log(y)
* tfdbg有一个功能,可以轻松地跟踪Tensors和操作回到Python源文件中的行。它可以用它们创建的ops或Tensors来注释Python文件的行。要使用此功能,只需单击ni -t <op_name>命令的堆栈跟踪输出中的下划线行号 ,或使用ps(或print_source)命令,如: ps /path/to/source.py。有关ps输出示例,请参阅下面的屏幕截图:

对输入应用值剪辑tf.log 以解决此问题:

diff = y_ * tf.log(tf.clip_by_value(y, 1e-8, 1.0))
现在,再试一次--debug
python -m tensorflow.python.debug.examples.debug_mnist --debug
输入run -f has_inf_or_nantfdbg>提示并确认没有张量标记为包含naninf价值观,准确性不再被卡住。成功!

 

调试tf学习估计器

有关文档tfdbg调试 tf.contrib.learn Estimator S和ExperimentS,请参阅 如何使用tf.contrib.learn使用TensorFlow调试器(tfdbg) 

 

离线调试远程运行的会话

通常,您的模型正在远程机器或进程中运行,您没有终端访问。要在这样的情况下进行模型调试,你可以使用offline_analyzertfdbg。它对转储的数据目录进行操作。如果您正在运行的进程是用Python编写的,则可以使用该方法配置RunOptions您称之为Session.run()方法的proto tfdbg.watch_graph。当Session.run()呼叫发生时,这将导致中间张量和运行时图形转储到您选择的共享存储位置。例如:

from tensorflow.python.debug import debug_utils

# ... Code where your session and graph are set up...

run_options = tf.RunOptions()
debug_utils.watch_graph(
      run_options,
      session.graph,
      debug_urls=["file:///shared/storage/location/tfdbg_dumps_1"])
# Be sure to use different directories for different run() calls.

session.run(fetches, feed_dict=feeds, options=run_options)

后来,在你不得不终端接入的环境中,你可以加载和通过检查在共享存储转储目录中的数据 offline_analyzertfdbg。例如:

python -m tensorflow.python.debug.cli.offline_analyzer \
    --dump_dir=/shared/storage/location/tfdbg_dumps_1

Session包装DumpingDebugWrapperSession提供了产生可以离线分析上的文件系统转储更方便,更灵活的方式。要使用它,只需做:

# 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.debug import debug_utils

sess = tf_debug.DumpingDebugWrapperSession(
    sess, "/shared/storage/location/tfdbg_dumps_1/", watch_fn=my_watch_fn)

watch_fn=my_watch_fnCallable,它允许您配置什么 Tensors到观看不同的Session.run()呼叫,的功能fetches,并feed_dictrun()通话和其他国家。有关 详细信息,请参阅 DumpingDebugWrapperSession的API文档

如果您使用C ++或其他语言编写代码,还可以修改生成可以离线检查的调试转储的debug_options字段RunOptions。有关 详细信息,请参阅 原始定义

 

tfdbg CLI的其他功能

  • 使用向上和向下箭头键导航命令历史记录。还支持基于前缀的导航。
  • 使用prevnext 命令导航屏幕输出的历史记录,或通过点击屏幕顶部附近的下划线<---->链接。
  • 选项卡完成命令和一些命令参数。
  • 使用bash风格的重定向将屏幕输出写入文件。例如:
tfdbg> pt cross_entropy/Log:0[:, 0:10] > /tmp/xent_value_slices.txt

 

经常问的问题

输出左侧的时间戳是否lt反映在非调试会话中的实际性能?

A:否。调试器将附加的专用调试节点插入到图形中以记录中间张量的值。这些节点肯定会减慢图形执行速度。如果您有兴趣分析您的模型,请查看 tfprof 和其他TensorFlow分析工具。

如何在Bazel中链接tfdbg Session?为什么会看到诸如“ImportError:不能导入名称调试”之类的错误?

A:在你的BUILD规则中,声明依赖关系:"//tensorflow:tensorflow_py""//tensorflow/python/debug:debug_py"。第一个是您使用TensorFlow即使没有调试器支持的依赖关系; 第二个启用调试器。然后,在你的Python文件中,添加:

from tensorflow.python import debug as tf_debug

# Then wrap your TensorFlow Session with the local-CLI wrapper.
sess = tf_debug.LocalCLIDebugWrapperSession(sess)

tfdbg是否帮助调试运行时错误,如形状不匹配?

:是的。tfdbg拦截运行时由op产生的错误,并在CLI中向用户显示带有一些调试指令的错误。参见示例:

# Debugging shape mismatch during matrix multiplication.
python -m tensorflow.python.debug.examples.debug_errors \
    --error shape_mismatch --debug

# Debugging uninitialized variable.
python -m tensorflow.python.debug.examples.debug_errors \
    --error uninitialized_variable --debug

为什么我不能在tfdbg CLI中选择文本?

:这是因为tfdbg CLI默认启用终端中的鼠标事件。此鼠标面罩模式将覆盖默认终端交互,包括文本选择。您可以使用命令mouse off或者 重新启用文本选择m off

开源TensorFlow中tfdbg CLI 的平台特定系统要求是什么?

A:在Mac OS X上,ncurses库是必需的。可以安装 brew install homebrew/dupes/ncurses。在Windows上,pyreadline库是必需的。如果您使用Anaconda3,您可以使用诸如此类的命令来安装它 "C:\Program Files\Anaconda3\Scripts\pip.exe" install pyreadline

 

  • 无标签