TensorFlow官方教程翻译1:TensorFlow调试器

原文地址:https://www.tensorflow.org/programmers_guide/debugger

TensorFlow调试器是TensorFlow专门的调试器。它提供运行的TensorFlow的图其内部的结构和状态的可见性。从这种可见性中获得的洞察力有利于调试各种模型在训练和推断中出现的错误。

这个教程将展现tfdbg的命令行界面的功能,并聚焦于如何调试在TensorFLow的模型开发中经常发生的一种错误:错误数值(nan和inf)导致的训练失败。

为了观察这个问题,在没有调试器的情况下,运行下列代码:

python -mtensorflow.python.debug.examples.debug_mnist

这个代码训练了一个简单的神经网络用来识别MNIST数字图片。请注意,准确率在第一次训练后,微微上升,但是接着停滞在了一个比较低(近机会)的水平:

抓抓脑袋,你怀疑肯定是在训练中,图中的一些节点产生了比如inf和nan这样的坏的数值。TensorFlow的计算图模型使得其不用用类似于Python的pdb等多用途的调试器来调试例如模型内部状态。tfdbg专门用来诊断这中类型的问题,并查明问题首先暴露出来的那个确切的节点。

用tfdbg包装TensorFlow会话

为了在我们的样例中添加tfdbg的支持,我们只需要添加下列三行代码,这三行代码会在提供了—debug标识的时候,用一个调试器包装器来包装会话对象:



这个包装器有会话对象相同的接口,因此启动调试不需要对于代码做其他的修改。但是包装器提供其他的功能,包括:

l在每次run()调用之前或者之后,提供一个基于终端的用户接口,让你控制运行,并检查图的内部状态

l让你可以为张量的数值注册特殊的过滤器,以此来方便问题的诊断。

在这个例子中,我们将注册一个称作tfdbg.has_inf_or_nan的张量过滤器,它仅仅确定了图中的任何一个中间张量,是否存在任何的nan或者inf数值。(这个过滤器是一个普遍的样例,我们使用debug_data模块来运行它)

defhas_inf_or_nan(datum,tensor):

returnnp.any(np.isnan(tensor))ornp.any(np.isinf(tensor))

建议:你可以写你自己定义的过滤器。参见DebugDumpDir.find()的API文档获取额外的信息。

用tfdbg调试模型训练

让我们在开启调试的情况下,再次训练模型。运行上面提到的指令,这次增加—debug标志:

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

调试包装器会话会在将要运行第一次run()调用的时候,弹出给你,并有关于获取的张量和供给字典的信息显示在屏幕上。

这就是我们所提到的运行-启动用户接口。如果屏幕尺寸太小,不足以显示消息的整个内容,你可以调整它的大小,或者用PageUp/PageDown/Home/End键来浏览屏幕上的输出。

正如屏幕所显示的,第一次调用run()使用测试集计算准确率,也就是一个图上的前向传递。你可以输入run(或者它的简写r)来启动run()的调用。在终端上同样支持鼠标事件,你可以只点击屏幕左上角的带下划线的run来运行。

这会在run()调用刚结束的时候启动另外一个屏幕,它会显示所有这次运行中被转储的中间张量。(这些张量也可以通过在你执行run之后,运行命令lt来获取。)这被称作运行-结束用户接口:

tfdbg CLI常用指令

在tfdbg>弹出界面尝试下列命令(参考代码tensorflow/python/debug/examples/debug_mnist.py)

在第一调用run()的时候,没有有问题的数据值。你可以使用run命令或者他的缩写r,来接着运行下一个run。

建议:如果你重复的输入run或者r,你将会让run()调用进入序列模式。

你也可以使用-t参数来指定一次运行run()的次数,例如

tfdbg>run-t10

除了重复的输入run,并在每次run()之后,手动的在运行-结束用户界面搜索nan和inf,你还可以使用下列命令让调试器不用再运行前和运行后停止并弹出,并重复的执行run()调用知道nan或者inf第一次出现在图中。这类似于一些程序语言调试器的条件中断:

tfdbg>run-f has_inf_or_nan

注意:这个能成功是因为我们之前为nan和inf注册了一个名为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()调用后立即停止了,因为这个run调用产生了中间张量,传递给了指定的过滤器has_inf_or_nan:

如屏幕显示所示,has_inf_or_nan过滤器在第四次运行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)

为什么出现了这些无穷大?为了更进一步的调试,显示更多关于节点cross_entropy/Log的信息,可以通过点击顶部下划线的node_info菜单选项或者输出相同的命令:

tfdbg>ni cross_entropy/Log

你可以看到这个节点由个操作类型为Log,并且它的输入节点是softmax/Softmax。运行下列指令来更进一步的查看输入张量:

tfdbg>pt softmax/Softmax:0

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

tfdbg>/0\.000

确实有零的存在。现在清楚了,坏的数据值的源头是节点cross_entropy/Log计算零的对数值。为了找到相关的Python源码,使用-t标志的ni参数命令来追溯节点的构建:

tfdbg>ni-t cross_entropy/Log

如果你使用在屏幕顶部的可点击的node_info菜单项目,那么-t标志是默认使用的。

从追溯中可以看到,操作是在代码debug_mnist.py:105-106行创建的:

diff=y_*tf.log(y)

*tfdbg的功能使得追溯张亮和操作到Python源文件中每行变得容易。它可以用操作或者张量注释创建它们的Python文件的每行。为了使用这个功能,只需点击ni –t 指令的堆栈输出中的有下划线的数字,或者使用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

输入在弹出的tfdbg>界面,输入run –f has_inf_or_nan,从而确定没有张量被标记为含有nan或者inf的数值,这样准确率就不再停滞不前了。成功!

调试tf-learn评估器

对于在tfdbg上调试tf.contrib.learn评估器和实验的文档,请参考How to Use TensorFlow

Debugger (tfdbg) with tf.contrib.learn.

离线调试远程运行的会话

有时候,你的模型运行在远程的机器或者进程上,你无法通过终端接触到。为了在这种情况下运行模型调试,你可以使用tfdbg的offline_analyzer。它运行在转储的数据字典上。如果你运行的进程是用Python写的,你可以使用tf.dbg.watch_graph方法,在调用Session.run()的时候,配置RunOption的原型。这会导致,在Session.run()被调用时,中间的张量和运行时的图被转储到你选择的一个共享存储位置上。例如:

fromtensorflow.python.debugimportdebug_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)

晚些时候,你可以用终端接触的环境中,你可以载入并且查看这些使用tfdbg的offline_analyzer存储在共享存储空间的转储字典上的数据。例如:

python-m tensorflow.python.debug.cli.offline_analyzer\

--dump_dir=/shared/storage/location/tfdbg_dumps_1

会话包装器

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.)

fromtensorflow.python.debugimportdebug_utils

sess=tf_debug.DumpingDebugWrapperSession(

sess,"/shared/storage/location/tfdbg_dumps_1/",watch_fn=my_watch_fn)

watch_fn=my_watch_fn是可调用的,它允许你在不同的Session.run()调用中,配置查看的张量,作为对于run()调用和其他状态的获取以及feed_dict的函数。参考the

API doc of DumpingDebugWrapperSession获得更多详情。

如果你的模型是用C++或者其他语言写的,你也可以修改RunOptions的debug_options域来产生可以离线查看的调试转储文件。参考the

proto definition获得更多细节。

tfdbg命令行界面的其他功能

l使用上下键浏览命令历史记录。支持基于前缀的导航。

l使用prev或者next的命令,或者点击屏幕顶部的下划线的<--和-->链接,来浏览屏幕输出的历史记录

lTab补全命令和一些命令的参数

l使用bash风格的重定位将屏幕输出写入文件。例如:

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

常见问题

Q:在lt命令输出的左侧的时间戳反应了非调试模式的真实性能吗?

A:没有。调试器在图中插入了额外的特殊目的的调试节点,来记录中间的张量的数值。这些节点肯定会减缓图的运行。如果你对剖析你的模型感兴趣,查看TensorFlow的tfprof和其他剖析工具。

Q:我怎样把tfdbg和我在Bazel里的会话连接起来?为什么我看到一个错误:ImportError:cannot

import name debug?

A:在你构建的规则中(BUILD rule),声明依赖:"//tensorflow:tensorflow_py"和"//tensorflow/python/debug:debug_py"。你包含的第一个依赖是使用没有即使调试器支持的TensorFlow;第二个开启调试器。然后在你的Python文件中,增加:

fromtensorflow.pythonimportdebugastf_debug

# Then wrap your TensorFlow Session with the local-CLI wrapper.

sess=tf_debug.LocalCLIDebugWrapperSession(sess)

Q:tfdbg能帮助调试运行时的,类似于形状不匹配的错误吗?

A:可以。tfdbg在运行时拦截由操作产生的错误,并且在命令行界面呈现这些错误以及一些调试指引。查看例子:

# 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

Q:怎么才能使我的tfdbg包装的会话或者钩子仅在主线程中运行调试模式?

A:这是一个常见的使用例子,例子中的Session对象被同时的用于多个线程。典型地,子线程看管类似于运行入队操作的后台任务。你时常仅仅需要调试主线程(或者稍不频繁地,仅仅一个子线程)。你可以使用LocalCLIDebugWrapperSession的thread_name_filter关键字参数来获取这种类型的选择线程的调试。例如,你想要只调试主线程,你可以用:

sess=tf_debug.LocalCLIDebugWrapperSession(sess,thread_name_filter="MainThread$"

上面的例子依赖于一个事实,在Python中的主线程有个默认名为MainThread。

Q:我正在调试的模型很大。被tfdbg转储的数据占满了我硬盘的空闲空间。我该怎么办?

A:对于巨大的模型,比如有很多中间的张量的模型,有个别中间张量有巨大尺寸的模型和/或者图中在任何tf.while_loops中有很多迭代,这种磁盘空间问题都会发生。

有三种可能的变通方案或者解决办法:

1.LocalCLIDebugWrapperSession和LocalCLIDebugHook的构造器提供一个关键字参数dump_root,有了这个参数你可以指定tfdbg转储调试数据的路径。例如:

```python # 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会在退出前清空这个目录。

2.在运行时,减少使用的批处理的大小。

3.使用tfbdg的过滤器选项运行命令,仅查看图中特殊的节点。例如:

tfdbg> run --node_name_filter .*hidden.*

tfdbg> run --op_type_filter Variable.* tfdbg> run --tensor_dtype_filter int.*

Q:为什么我不能再tfdbg命令行界面选择文本?

A:这是因为tfdbg命令行界面在终端中默认开启了鼠标事件。这个鼠标-任务模式重载了默认的控制台交互,其中包括文本选择。你可以使用命令mouse off或者m off来重新开启文本选择。

Q:开源的TensorFlow中的tfdbg命令行界面对于特殊平台系统的要求是什么?

A:在Mac OS X,需要ncurses库。它可以用brew install homebrew/dupes/ncurses安装。在Windows下,需要pyreadline库。如果你使用Anaconda3你可以使用比如C:\Program Files\Anaconda3\Scripts\pip.exe的指令安装pyreadline。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • 总有人说:留不下的城市,回不去的农村。看似无奈,其实更多的是你自己如何选择的问题,总有人过着我们想要的生活,愿你我...
    曾林月阅读 1,501评论 16 13
  • 佛的空性-什麼是真正的保護 空中读书会笔记2016/12/21 一年三个月的空中读书会,带来钻石般闪光的回忆, 可...
    敏乐麻麻阅读 474评论 0 1
  • 一个白人天主教徒来到天堂门口想要进去,他跟守门人列举了自己的种种善行,但守门人说:“可以,不过你还必须能够正确拼写...
    日更飘阅读 1,024评论 0 1
  • 01 “老顾有了二春了吧,看你越活越年轻了呀” 人逢喜事精神爽,最近老顾时不时的听到小区的街坊邻居们这样打趣他,心...
    瑶瑶妈阅读 999评论 21 15
  • 文/一土 两年前,我认识一个奓山的同事。她长得胖,是那种看上去脸上堆笑的女生。我对胖子并没有成见,相反很乐意与他们...
    雨下撒哈拉阅读 456评论 0 0