Debugging TensorFlow Programs(调试TensorFlow程序)
调试TensorFlow程序
TensorFlow 调试器(tfdbg
)是 TensorFlow 的专用调试器。它允许您在训练和推理期间查看运行 TensorFlow 图形的内部结构和状态,由于 TensorFlow 的计算图范例,使用通用调试器很难调试Pythonpdb
注意:支持的外部平台上的tfdbg的系统要求包括以下内容。在Mac OS X上,该
ncurses
库是必需的。它可以安装brew install homebrew/dupes/ncurses
。在Windows上,pyreadline
是必需的。如果你使用Anaconda3,你可以使用一个命令来安装它"C:\Program Files\Anaconda3\Scripts\pip.exe" install pyreadline
。
本教程演示如何使用tfdbg
命令行界面(CLI)调试nan
和inf
的外观,这是TensorFlow模型开发中经常遇到的一种错误类型。以下示例适用于使用Session
TensorFlow 的低级API的用户。本文后面的部分将介绍如何将tfdbg
与更高级别的API一起使用,即tf-learn Estimator
s和Experiment
。要观察
这样的问题,请在没有调试器的情况下运行以下命令(可以在此处找到源代码):
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
s和nan
s,因为这是此类训练失败的常见原因。让我们使用tfdbg来调试这个问题,并确定出现这个数字问题的确切图节点。
用tfdbg包装TensorFlow会话
为了在我们的例子中添加对tfdbg的支持,所需要的就是添加下面的代码行并用调试器包装器来包装Session对象。该代码已添加到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具有相同的接口,因此启用调试时不需要对代码进行其他更改。包装提供了其他功能,包括:
- 在
Session.run()
调用之前和之后调用CLI ,让您控制执行并检查图形的内部状态。
在这个例子中,我们已经注册了一个张量过滤器称为tfdbg.has_inf_or_nan
,它可以简单地确定是否存在任何中间张量中的任何值nan
或inf
张量(张量既不是Session.run()
调用的输入或输出,也是从输入到输出的路径中)。这个过滤器是用于nan
s和inf
s的,它是我们随debug_data
模块一起交付的常见用例。
注意:
您也可以编写自己的自定义过滤器。请参阅API文档的DebugDumpDir.find()
附加信息。
用tfdbg调试模型训练
让我们再次尝试训练模型,但这次--debug
添加了标志:
python -m tensorflow.python.debug.examples.debug_mnist --debug
调试包装会话将在您要执行第一次Session.run()
调用时提示您,并提供有关屏幕上显示的提取张量和Feed字典的信息。
这就是我们所说的运行启动CLI
。它Session.run
在执行任何事情之前列出了当前调用的提要和提取。
如果屏幕尺寸太小而无法全部显示信息内容,则可以调整它的大小。
使用PageUp
/ PageDown
/ Home
/ End
键导航屏幕输出。在大多数键盘上缺少这些键Fn + Up
/ Fn + Down
/ Fn + Right
/ Fn + Left
将会起作用。
在命令提示符处输入run
命令(或者只是r
):
tfdbg> run
该run
命令会导致tfdbg执行,直到下一次Session.run()
调用结束,该调用将使用测试数据集计算模型的准确性。tfdbg扩展运行时图形来转储所有中间张量。运行结束后,tfdbg会在运行端CLI中
显示所有转储的张量值。例如:
这张张量列表也可以在你执行run之后通过运行命令lt获得
tfdbg CLI经常使用的命令
在tfdbg>提示符下引用以下命令(引用代码tensorflow/python/debug/examples/debug_mnist.py):
命令 | 语法或选项 | 说明 | 例 |
---|---|---|---|
It | | 列举转储张量。 | It |
| -n <name_pattern> | 列出具有匹配给定正则表达式模式的名称的转储张量。 | lt -n Softmax.* |
| -t <op_pattern> | 列出具有匹配给定正则表达式模式的op类型的转储张量。 | lt -t MatMul |
| -s <sort_key> | 按给定的sort_key对输出进行排序,其可能的值是timestamp(缺省值),dump_size,op_type和tensor_name。 | lt -s dump_size |
| -r | 按相反顺序排序。 | lt -r -s dump_size |
pt | | 转储张量的打印值。 | |
| pt <张量> | 打印张量值。 | hidden/Relu:0 |
| pt <张量>切片 | 使用numpy样式阵列切片打印张量子阵列。 | pt hidden/relay:00:50, : |
| -a | 打印整个大张量,而不使用椭圆。(可能需要很长时间才能获得较大张量。) | pt -a hidden/Relu:00:50, : |
| -r <范围> | 突出显示落入指定数值范围的元素。多个范围可以结合使用。 | pt hidden/Relu:0 -a -r [-inf,-1,1,inf] |
| -s | 包括张量数值的摘要(仅适用于布尔型和数值型非空张量,如int *和float *)。 | pt -s hidden/Relu:00:50, : |
@coordinates | | 导航到pt输出中的指定元素。 | @ 10,0 or @ 10,0 |
/regex | | 给定正则表达式的风格较少的搜索。 | /INF |
/ | | 滚动到搜索正则表达式匹配的下一行(如果有的话)。 | / |
pf | | 在Session.run的feed_dict中打印一个值。 | |
| pf <feed_tensor_name> | 打印feed_dict的值。另请注意,pf命令具有-a,-r和-s标志(未在下面列出),它们与pt的同名标志具有相同的语法和语义。 | pf input_xs:0 |
eval | | 评估任意Python和numpy表达式。 | |
| eval <表达式> | 评估一个Python/numpy表达式,numpy可用作np并调试反引号中的张量名称。 | eval "np.matmul(( output/Identity:0 / Softmax:0 ).T, Softmax:0 )" |
| -a | 全面打印大型评估结果,即不使用省略号。 | eval -a 'np.sum(Softmax:0, axis = 1)' |
ni | | 显示节点信息。 | |
| -a | 在输出中包含节点属性。 | ni -a hidden/Relu |
| -d | 列出节点中可用的调试转储。 | ni -d hidden/Relu |
| -t | 显示节点创建的Python堆栈跟踪。 | ni -t hidden/Relu |
li | | 列出节点的输入 | |
| -r | 递归地列出节点的输入(输入树)。 | li -r hidden/ Relu:0 |
| -d <max_depth> | 在-r模式下限制递归深度。 | li -r -d 3 hidden/Relu:0 |
| -c | 包含控制输入。 | li -c -r hidden/Relu:0 |
lo | | 列出节点的输出收件人 | |
| -r | 递归列出节点的输出接收者(输出树)。 | lo -r hidden/Relu:0 |
| -d <max_depth> | 在-r模式下限制递归深度。 | lo -r -d 3 hidden/Relu:0 |
| -c | 通过控制边包括收件人。 | lo -c -r hidden/Relu:0 |
ls | | 列出参与节点创建的Python源文件。 | |
| -p <路径模式> | 将输出限制为与给定正则表达式路径模式匹配的源文件。 | ls -p .* debug_mnist.* |
| -n | 将输出限制为与给定正则表达式模式匹配的节点名称。 | ls -n Softmax.* |
ps | | 打印Python源文件。 | |
| ps <文件路径> | 打印给定的Python源文件source.py,并用每个节点创建的节点注释行(如果有的话)。 | ps /path/to/source.py |
| -t | 对Tensors执行注释,而不是默认的节点。 | ps -t /path/to/source.py |
| -b <line_number> | 从给定的行开始注释source.py。 | ps -b 30 /path/to/source.py |
| -m <max_elements> | 限制每行的注释中的元素数量。 | ps -m 100 /path/to/source.py |
run | | 继续下一个Session.run() | run |
| -n | 在没有调试的情况下执行下一个Session.run,然后在运行之前立即下降到CLI。 | run -n |
| -t <T> | 在没有调试的情况下执行Session.run T-1次,然后运行调试。然后在调试运行后立即下降到CLI。 | run -t 10 |
| -f <filter_name> | 继续执行Session.run,直到任何中间张量触发指定的张量过滤器(导致过滤器返回True)。 | run -f has_inf_or_nan |
| --node_name_filter <pattern> | 执行下一个Session.run,仅查看名称与给定的正则表达式模式匹配的节点。 | run --node_name_filter Softmax.* |
| --op_type_filter <pattern> | 执行下一个Session.run,只观察op类型与给定正则表达式模式匹配的节点。 | run --op_type_filter Variable.* |
| --tensor_dtype_filter <pattern> | 执行下一个Session.run,只转储数据类型(dtypes)与给定正则表达式模式匹配的张量。 | run --tensor_dtype_filter int.* |
| -p | 在分析模式下执行下一个Session.run调用。 | run -p |
ri | | 显示有关运行当前运行的信息,包括提取和提要。 | ri |
help | | 打印一般帮助信息 | help |
| help <command> | 打印给定命令的帮助。 | help it |
请注意,每次输入命令时,都会显示新的屏幕输出。这有点类似于浏览器中的网页。您可以通过点击这些屏幕间导航<--和-->附近的CLI的左上角的文字箭头。
tfdbg CLI的其他功能
除了上面列出的命令外,tfdbg CLI还提供了以下附加功能:
- 要浏览以前的tfdbg命令,请输入几个字符,然后按向上或向下箭头键。tfdbg将向您显示以这些字符开始的命令的历史记录。
tfdbg> pt cross_entropy/Log:0[:, 0:10] > /tmp/xent_value_slices.txt
寻找nans和infs
在第一次Session.run()
调用中,碰巧没有问题的数值。您可以使用该命令run
或其简写形式继续下一次运行r
。
提示:如果您输入run或r重复输入,您将能够以Session.run()顺序方式移动呼叫。您也可以使用该-t标志一次向前移动多个Session.run()呼叫,例如:tfdbg> run -t 10
在每次调用之后(例如,通过使用上表中显示的命令),可以使用以下命令让调试器在不停止的情况下重复执行调用,而不是在运行结束UI中run
反复输入和手动搜索nan
s和inf
s 在运行开始或运行结束提示符下,直到第一个或值出现在图中。这类似于某些过程式语言调试器中的条件断点
:Session.run()ptSession.run()naninf
tfdbg> run -f has_inf_or_nan
注:上述命令可正常工作,因为has_inf_or_nan创建包装会话时已为您注册称为张量过滤器。这个过滤器检测nans和infs(如前所述)。如果您已注册任何其他过滤器,则可以使用“run -f”使tfdbg运行,直到任何张量触发该过滤器(导致过滤器返回True)。def my_filter_callable(datum,tensor):#一个检测零值标量的过滤器。返回len(tensor.shape)== 0和张量== 0.0 sess.add_tensor_filter('my_filter',my_filter_callable)然后在tfdbg运行启动提示符运行,直到触发过滤器:tfdbg> run -f my_filter
请参见本API文档的谓词的预期的签名和返回值的详细信息Callable
与使用add_tensor_filter()
。
当屏幕显示在第一行显示时,has_inf_or_nan
过滤器在第四次Session.run()
调用期间首先被触发:图表上的亚当优化器前向 - 后向训练过程。在这个运行中,36个(全部95个)中间张量包含nan
或inf
值。这些张量按时间顺序列出,其时间戳显示在左侧。在列表顶部,您可以看到第一个张量,其中不良数值首先出现:cross_entropy/Log:0
。
要查看张量的值,请单击带下划线的张量名称cross_entropy/Log:0
或输入等效命令:
tfdbg> pt cross_entropy/Log:0
向下滚动一下,你会发现一些分散的inf
值。如果实例inf
和实例nan
很难找到,可以使用以下命令执行正则表达式搜索并突出显示输出:
tfdbg> /inf
Or, alternatively:
tfdbg> /(inf|nan)
您还可以使用-s
或--numeric_summary
命令快速总结张量中的数值类型:
tfdbg> pt -s cross_entropy/Log:0
从总结中,可以看到cross_entropy/Log:0
张量的1000个元素中有几个是-inf
s(负无穷)。
为什么会出现这些无穷大?要进一步调试,cross_entropy/Log
通过单击node_info
顶部带下划线的菜单项或输入等效的node_info
(ni
)命令来显示有关节点的更多信息:
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”,tfdbg会自动显示节点构造的回溯。
从回溯中,您可以看到op在以下行构建debug_mnist.py
::
diff = y_ * tf.log(y)
tfdbg具有一个功能,可以很容易地将张量和操作追溯回Python源文件中的行。它可以用它们创建的ops或Tensors注释Python文件的行。要使用此功能,只需单击ni -t <op_name>命令的堆栈跟踪输出中带下划线的行号,或使用ps(或print_source)命令(如:)ps /path/to/source.py。例如,以下屏幕截图显示了ps命令的输出。
解决问题
要解决该问题,请编辑debug_mnist.py
,更改原始行:
diff = -(y_ * tf.log(y))
到Softmax交叉熵的内置数值稳定实现:
diff = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=logits)
重新运行--debug
标志如下:
python -m tensorflow.python.debug.examples.debug_mnist --debug
在tfdbg>提示符处输入以下命令:
run -f has_inf_or_nan`
确认没有张量被标记为包含nan
或inf
值,并且精度现在继续上升而不是卡住。成功!
调试tf-learn估计器和实验
本节介绍如何调试使用Estimator
和Experiment
API的TensorFlow程序。这些API提供的部分便利是它们Session
在内部管理。这使得LocalCLIDebugWrapperSession
前面几节中的描述不适用。幸运的是,您仍然可以使用hook
提供的特殊s 来调试它们tfdbg
。
调试tf.contrib.learn估计器
目前,tfdbg
可以调试tf-learn 的方法。要进行调试,请在参数中创建并提供它。例如:fit()
evaluate()EstimatorEstimator.fit()LocalCLIDebugHookmonitors
# First, 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
# Create a LocalCLIDebugHook and use it as a monitor when calling fit().
hooks = [tf_debug.LocalCLIDebugHook()]
classifier.fit(x=training_set.data,
y=training_set.target,
steps=1000,
monitors=hooks)
要进行调试Estimator.evaluate()
,请将挂钩分配给该hooks
参数,如下例所示:
accuracy_score = classifier.evaluate(x=test_set.data,
y=test_set.target,
hooks=hooks)["accuracy"]
debug_tflearn_iris.py,基于{$ tflearn $ tflearn的虹膜教程},包含如何使用tfdbg一个完整的例子Estimator
秒。要运行这个例子,请执行:
python -m tensorflow.python.debug.examples.debug_tflearn_iris --debug
调试tf.contrib.learn实验
Experiment
是一个tf.contrib.learn
比更高层次的构造Estimator
。它提供了一个用于培训和评估模型的单一界面。要调试train()
和evaluate()
调用Experiment
对象,可以分别在调用其构造函数时使用关键字参数train_monitors
和eval_hooks
。例如:
# First, 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.LocalCLIDebugHook()]
ex = experiment.Experiment(classifier,
train_input_fn=iris_input_fn,
eval_input_fn=iris_input_fn,
train_steps=FLAGS.train_steps,
eval_delay_secs=0,
eval_steps=1,
train_monitors=hooks,
eval_hooks=hooks)
ex.train()
accuracy_score = ex.evaluate()["accuracy"]
要debug_tflearn_iris
在Experiment
模式下构建和运行示例,请执行以下操作:
python -m tensorflow.python.debug.examples.debug_tflearn_iris \
--use_experiment --debug
LocalCLIDebugHook
也允许你配置一个watch_fn
可以用来灵活指定Tensor
在不同的Session.run()
调用中看什么的函数,这是fetches
和feed_dict
和其他状态的函数。有关更多详情,请参阅此API文档。
用TFDBG调试Keras模型
若要使用TFDBG Keras,让Keras后端使用TFDBG包裹的Session对象。例如,要使用CLI包装器:
import tensorflow as tf
from keras import backend as keras_backend
from tensorflow.python import debug as tf_debug
keras_backend.set_session(tf_debug.LocalCLIDebugWrapperSession(tf.Session()))
# Define your keras model, called "model".
model.fit(...) # This will break into the TFDBG CLI.
用TFDBG调试tf-slim
TFDBG目前仅支持tf-slim培训训练。要调试训练过程中,提供LocalCLIDebugWrapperSession
给session_wrapper
的说法slim.learning.train()
。例如:
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)
脱机调试远程运行会话
通常,您的模型运行在远程机器上或您没有终端访问权限的进程中。要在这种情况下执行模型调试,可以使用offline_analyzer
(在下面描述)的offline_analyzer
二进制tfdbg
。它在转储的数据目录上运行。这可以针对较低级别的Session
API以及较高级别的API Estimator
和Experiment
API来完成。
调试远程tf.Sessions
如果您直接与tf.Session
API 交互,则python
可以使用该方法配置RunOptions
您调用Session.run()
方法的原型tfdbg.watch_graph
。这会导致中间张量和运行时图形在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)
稍后,在您有终端访问权的环境中(例如,可以访问上面代码中指定的共享存储位置的本地计算机),您可以使用以下命令加载和检查共享存储上转储目录中的数据offline_analyzer
二进制tfdbg
。例如:
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
是允许您配置什么tensor
s到观看不同的Session.run()
调用,fetches
的功能,并feed_dict
在run()
调用和其他国家。
C ++和其他语言
如果您的模型代码是用C ++或其他语言编写的,那么您还可以修改该debug_options
字段RunOptions
以生成可以脱机检查的调试转储。有关更多详细信息,请参阅原型定义。
调试远程运行tf-learn估计器和实验
如果您的远程TensorFlow服务器运行Estimator
s,则可以使用非交互式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")]
然后,hook可以按照LocalCLIDebugHook本文档前面所述示例的相同方式使用它。由于训练和/或评价; Estimator或Experiment发生,tfdbg创建具有下列名称模式目录:/shared/storage/location/tfdbg_dumps_1/run_<epoch_timestamp_microsec>_<uuid>。每个目录对应于Session.run()呼叫fit()或evaluate()调用的基础。您可以使用offline_analyzertfdbg提供的离线方式加载这些目录并在命令行界面中检查它们。例如:
python -m tensorflow.python.debug.cli.offline_analyzer \
--dump_dir="/shared/storage/location/tfdbg_dumps_1/run_<epoch_timestamp_microsec>_<uuid>"
经常问的问题
问
:输出左侧的时间戳是否
反映了非调试会话中的实际性能?
答
:不可以。调试器会在图表中插入额外的专用调试节点来记录中间张量的值。这些节点减慢了图形的执行速度。如果您对分析模型感兴趣,请查看
- tfdbg的分析模式:tfdbg> run -p。
问
:我如何将tfdbg与
Bazel中的我联系起来?为什么我会看到如“ImportError:无法导入名称调试”的错误?Session
答
:在您的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在运行时拦截ops生成的错误,并在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包装的Sessions或Hooks只从主线程运行调试模式?
答
:这是一个常见的用例,其中Session
对象是从多个线程并发使用的。通常,子线程负责后台任务,如运行入队操作。通常情况下,您只想调试主线程(或者不太频繁,只有一个子线程)。您可以使用thread_name_filter
关键字参数LocalCLIDebugWrapperSession
来实现这种类型的线程选择性调试。例如,要仅从主线程调试,请Session
按如下所示构造一个包装:
sess = tf_debug.LocalCLIDebugWrapperSession(sess, thread_name_filter="MainThread$")
上面的例子依赖于Python中的主线程具有默认名称MainThread
的事实。
问
:我正在调试的模型非常大。tfdbg转储的数据填满了我磁盘的可用空间。我能做什么?
答
:在以下任何情况下,您可能会遇到此问题:
- 具有许多中间张量的模型
有三种可能的解决方法或解决方案:
- 构造函数
LocalCLIDebugWrapperSession
并LocalCLIDebugHook
提供关键字参数,dump_root
以指定tfdbg转储调试数据的路径。您可以使用它来让tfdbg将调试数据转储到具有较大可用空间的磁盘上。例如:
# For LocalCLIDebugHook hooks = [tf\_debug.LocalCLIDebugHook(dump\_root="/with/lots/of/space")] ``` Make sure that the directory pointed to by dump_root is empty or nonexistent. tfdbg cleans up the dump directories before exiting. * Reduce the batch size used during the runs. * Use the filtering options of tfdbg's`run` command to watch only specific nodes in the graph. For example:
`tfdbg> run --node_name_filter .*hidden.* tfdbg> run --op_type_filter Variable.* tfdbg> run --tensor_dtype_filter int.*`
The first command above watches only nodes whose name match the regular-expression pattern `.*hidden.*`. The second command watches only operations whose name match the pattern `Variable.*`. The third one watches only the tensors whose dtype match the pattern `int.*` (e.g., `int32`).
**Q**: _Why can't I select text in the tfdbg CLI?_
**A**: This is because the tfdbg CLI enables mouse events in the terminal by default. This [mouse-mask](https://linux.die.net/man/3/mousemask) mode overrides default terminal interactions, including text selection. You can re-enable text selection by using the command `mouse off` or `m off`.
**Q**: _Why does the tfdbg CLI show no dumped tensors when I debug code like the following?_
```javascript
a = tf.ones(10, name="a")
b = tf.add(a, a, name="b")
sess = tf.Session()
sess = tf_debug.LocalCLIDebugWrapperSession(sess)
sess.run(b)
**A**: The reason why you see no data dumped is because every node in the executed TensorFlow graph is constant-folded by the TensorFlow runtime. In this exapmle, `a` is a constant tensor; therefore, the fetched tensor `b` is effectively also a constant tensor. TensorFlow's graph optimization folds the graph that contains `a` and `b` into a single node to speed up future runs of the graph, which is why `tfdbg` does not generate any intermediate tensor dumps. However, if `a` were a [`tf.Variable`](https://www.tensorflow.org/api_docs/python/tf/Variable), as in the following example:
```javascript
import numpy as np
a = tf.Variable(np.ones10, 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
应显示中间张量转储。