发新帖

TensorFlow 学习 -- TensorFlow 调试程序(3)

[复制链接]
427 0

快来加入 TensorFlowers 大家庭!

您需要 登录 才可以下载或查看,没有帐号?加入社区

x
本帖最后由 大白白 于 2018-7-13 10:28 编辑

转载自:https://tensorflow.google.cn/programmers_guide/debugger?hl=zh-CN


使用 TFDBG 调试 tf-slim
TFDBG 支持对 tf-slim 进行训练和评估调试。如下所述,训练和评估需要略微不同的调试工作流程。


在 tf-slim 中调试训练流程
要调试训练流程,需要将 LocalCLIDebugWrapperSession 提供给 slim.learning.train() 的 session_wrapper 参数。例如:

import tensorflow as tf
from tensorflow.python import debug as tf_debug

# ... Code that creates the graph and the train_op ...
tf.contrib.slim.learning.train(
    train_op,
    logdir,
    number_of_steps=10,
    session_wrapper=tf_debug.LocalCLIDebugWrapperSession)

在 tf-slim 中调试评估流程
要调试评估流程,需要将 LocalCLIDebugHook 提供给 slim.evaluation.evaluate_once() 的 hooks 参数。例如:

import tensorflow as tf
from tensorflow.python import debug as tf_debug

# ... Code that creates the graph and the eval and final ops ...
tf.contrib.slim.evaluation.evaluate_once(
    '',
    checkpoint_path,
    logdir,
    eval_op=my_eval_op,
    final_op=my_value_op,
    hooks=[tf_debug.LocalCLIDebugHook()])


离线调试远程运行的会话
您的模型往往在您没有终端访问权限的远程机器或进程上运行。要在这种情况下调试模型,您可以使用 tfdbg 的 offline_analyzer 二进制文件(如下所述)。它在转储的数据目录上运行。可以对较低阶的 Session API 以及较高阶的 Estimator 和 Experiment API 执行此操作。
调试远程 tf.Sessions
如果您直接与 python 版 tf.Session API 互动,则可以使用方法 tfdbg.watch_graph 配置 RunOptions 原型(您使用此原型调用 Session.run() 方法)。这样一来,在发生 Session.run() 调用时,中间张量和运行时图会被转储到您选择的共享存储位置(以降低性能为代价)。例如:

from tensorflow.python import debug as tf_debug

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

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

session.run(fetches, feed_dict=feeds, options=run_options)
之后,在您拥有终端访问权限的环境(例如,一台可以访问上述代码指定的共享存储位置的本地计算机)中,您可以使用 tfdbg 的 offline_analyzer 二进制文件加载和检查共享存储上的转储目录中的数据。例如:

python -m tensorflow.python.debug.cli.offline_analyzer \
    --dump_dir=/shared/storage/location/tfdbg_dumps_1
Session 封装容器 DumpingDebugWrapperSession 提供了一种更简单、更灵活的方法来生成可离线分析的文件系统转储。要使用该方法,只需将您的会话封装到 tf_debug.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 import debug as tf_debug

sess = tf_debug.DumpingDebugWrapperSession(
    sess, "/shared/storage/location/tfdbg_dumps_1/", watch_fn=my_watch_fn)
watch_fn 参数接受 Callable,而后者允许您配置在不同的 Session.run() 调用期间要查看哪些 tensor,这些调用作为 run() 调用的 fetches 和 feed_dict 及其他状态的函数。


C++ 和其他语言
如果您的模型代码是采用 C++ 或其他语言编写的,则您还可以修改 RunOptions 的 debug_options 字段以生成可离线检查的调试转储。要了解详情,请参阅原型定义


调试远程运行的 tf-learn Estimator 和 Experiment
如果您在远程 TensorFlow 服务器上运行 Estimator,则您可以使用非交互式 DumpingDebugHook。例如:

# 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

hooks = [tf_debug.DumpingDebugHook("/shared/storage/location/tfdbg_dumps_1")]
然后,可以按照与本文档前面部分介绍的 LocalCLIDebugHook 示例一样的方法使用此 hook。在训练和/或评估 Estimator 或 Experiment 期间,tfdbg 会创建具有以下名称格式的目录:/shared/storage/location/tfdbg_dumps_1/run_<epoch_timestamp_microsec>_<uuid>。每个目录对应一个 Session.run() 调用,而此调用会成为 fit() 或 evaluate() 调用的基础。您可以使用 tfdbg 提供的 offline_analyzer 加载这些目录并以离线方式在命令行界面中进行检查。例如:

python -m tensorflow.python.debug.cli.offline_analyzer \
    --dump_dir="/shared/storage/location/tfdbg_dumps_1/run_<epoch_timestamp_microsec>_<uuid>"


常见问题解答
lt 输出左侧的时间戳是否反映了非调试会话的实际性能?
:否。调试程序在图中插入了其他特殊用途的调试节点来记录中间张量的值。这些节点减缓了图的执行。如果您对分析模型感兴趣,请查看:
  • tfdbg 的分析模式:tfdbg> run -p。
  • tfprof 和 TensorFlow 的其他分析工具。
如何在 Bazel 中将 tfdbg 与我的 Session 关联起来?为什么我会看到“ImportError: cannot import name debug”这样的错误?
:在您的 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 在运行时期间会拦截指令生成的错误,并在 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 封装的会话或钩子仅通过主线程运行调试模式?
:这是一个常见用例,其中 Session 对象同时在多个线程中使用。通常情况下,子线程负责后台任务,例如运行入列指令。您通常仅需要调试主线程(或者不太频繁地仅调试一个子线程)。您可以使用 LocalCLIDebugWrapperSession 的 thread_name_filter 关键字参数实现这种类型的线程选择性调试。例如,您要仅通过主线程进行调试,请按如下方式构造一个封装的 Session:

sess = tf_debug.LocalCLIDebugWrapperSession(sess, thread_name_filter="MainThread$")
以上示例的前提是 Python 中的主线程具有默认名称 MainThread。
我正在调试的模型非常大。tfdbg 转储的数据占满了磁盘的可用空间。我该怎么做?
:出现以下任何情况,您都可能会遇到此问题:
  • 模型具有很多中间张量
  • 中间张量非常大
  • 很多 tf.while_loop 迭代
有三种可能的解决方案:
  • LocalCLIDebugWrapperSession 和 LocalCLIDebugHook 的构造函数提供了一个关键字参数 dump_root,用于指定 tfdbg 转储调试数据的路径。您可以使用此参数让 tfdbg 将调试数据转储到可用空间比较多的磁盘上。例如:

# For LocalCLIDebugWrapperSession
sess = tf_debug.LocalCLIDebugWrapperSession(dump_root="/with/lots/of/space")

# For LocalCLIDebugHook
hooks = [tf_debug.LocalCLIDebugHook(dump_root="/with/lots/of/space")]
确保 dump_root 指向的目录为空或不存在。 tfdbg 在退出之前会清理转储目录。
  • 减小在运行期间使用的批次大小。
  • 使用 tfdbg 的 run 命令的过滤选项只查看图形中的特定节点。例如:

    tfdbg> run --node_name_filter .*hidden.*
    tfdbg> run --op_type_filter Variable.*
    tfdbg> run --tensor_dtype_filter int.*
    上面的第一个命令仅查看名称符合正则表达式格式 .*hidden.* 的节点。上面的第二个命令仅查看名称符合格式 Variable.* 的操作。上面的第三个命令仅查看 dtype 符合格式 int.*(例如 int32)的张量。

为什么不能在 tfdbg CLI 中选择文本?
:这是因为 tfdbg CLI 默认在终端中启用了鼠标事件。此 mouse-mask 模式会替换默认的终端交互,包括文本选择。您可以通过使用命令 mouse off 或 m off 来重新启用文本选择。
为什么我在调试如下代码时,tfdbg CLI 没有显示转储的张量?

a = tf.ones([10], name="a")
b = tf.add(a, a, name="b")
sess = tf.Session()
sess = tf_debug.LocalCLIDebugWrapperSession(sess)
sess.run(b)
:您之所以没有看到转储数据,是因为执行的 TensorFlow 图中的每个节点都由 TensorFlow 运行时进行了常数折叠处理。在本示例中,a 是一个常数张量;因此,已获取的张量 b 其实也是一个常数张量。TensorFlow 的图优化将包含 a 和 b 的图折叠成单个节点,以加快图的未来运行速度,因此,tfdbg 不会生成任何中间张量转储。不过,如果 a 是一个 tf.Variable,如下例所示:

import numpy as np

a = tf.Variable(np.ones[10], name="a")
b = tf.add(a, a, name="b")
sess = tf.Session()
sess.run(tf.global_variables_initializer())
sess = tf_debug.LocalCLIDebugWrapperSession(sess)
sess.run(b)
则不会发生常数折叠,tfdbg 应显示中间张量转储。
:我正在调试一个产生垃圾无穷数或 NaN 的模型。但是,我的模型中有一些节点已知会在输出张量中产生无穷值或 NaN,即使在完全正常的条件下也是如此。我如何在 run -f has_inf_or_nan操作期间跳过这些节点?
:使用 --filter_exclude_node_names(简称为 -fenn)标记。例如,如果您知道您有一个名称符合正则表达式 .*Sqrt.* 的节点,无论模型是否正常运行,该节点都会产生无穷数或 NaN,那么您可以使用命令 run -f has_inf_or_nan -fenn .*Sqrt.*,将节点从无穷数/NaN-finding 运行中排除。
:是否有用于 tfdbg 的 GUI?
:有,TensorBoard 调试程序插件就是 tfdbg 的 GUI。它提供了诸如计算图检查、张量值实时可视化、张量连续性和条件性断点以及将张量关联到其图形构建源代码等功能,所有这些功能都在浏览器环境中运行。要开始使用,请访问相关 README 文件


本楼点评(0) 收起
您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

快速回复 返回顶部 返回列表