TensorBoard Graph Visualization

TensorFlow 计算图是强大但复杂的。图可视化能帮助你理解并调试。这里是一个工作上可视化的例子:

命名空间(name scoping)和节点(nodes)

典型的 TensorFlow 图可以有数千个节点,多到难以一次全部看见,甚至不能用标准的图工具来显示。为了简化,variable 的 names 可以被 scoped 并使用这个信息去定义节点的层次(hierarchy)来可视化。默认只有最顶端的层次会被显示。下面用 tf.name_scope 在 name scope hidden 下定义了3个操作:

1
2
3
4
5
6
import tensorflow as tf

with tf.name_scope('hidden') as scope:
a = tf.constant(5, name='alpha')
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0), name='weights')
b = tf.Variable(tf.zeros([1]), name='biases')
/root/anaconda3/envs/tensorflow/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6
  return f(*args, **kwds)

这将产生下列3个 ops 的 names:

  • hidden/alpha
  • hidden/weights
  • hidden/biases

默认时,可视化工具将会将3个操作整合到一个节点,标签为 hidden。额外的详细信息不会丢失,你可以双击或者单击右上角的 + 号来展开节点,然后你将看到3个子节点,分别为 alpha,weights,biases。

下面是一个更复杂的节点的初始状态和展开状态的具体例子:

顶级名称域的初始视图pool_1,点击右上方橙色的+按钮或双击节点来展开。 展开的pool_1名称域视图,点击右上方橙色的-按钮或双击节点来收起此名称域。

通过命名空间整合节点是制作易读的图的关键。如果你建立一个模型,命名空间帮助你控制结果可视化。The better your name scopes, the better your visualization。

上面的图像例子说明了可视化的另一方面, TensorFlow 图表有两种连接关系:数据依赖和控制依赖。数据依赖显示两个操作之间的tensor流程,用实心箭头指示,而控制依赖用点线表示。在已展开的视图(上面的右图)中,除了用点线连接的CheckNumerics和control_dependency之外,所有连接都是数据依赖的。

还有一种手段用来简化布局。大多数 TensorFlow 图表有一部分节点,这部分节点和其他节点之间有很多连接。比如,许多节点在初始化阶段可能会有一个控制依赖,而绘制所有init节点的边缘和其依赖可能会创造出一个混乱的视图。

为了减少混乱,可视化把所有 high-degree 节点分离到右边的一个从属区域, 而不会绘制线条来表示他们的边。线条也不用来表示连接了,我们绘制了小节点图标来指示这些连接关系。分离出从属节点通常不会把关键信息删除掉,因为这些节点和内构功能是相关的。

节点conv_1被连接到save,注意其右边save节点图标。 save has a high degree, 并会作为从属节点出现,与conv_1的连接作为一个节点图标显示在其左边。为了继续减少杂乱,既然save有很多连接,我们则只显示前5个,而把其余的缩略为… 12 more。

最后一个结构上的简化法叫做序列折叠(series collapsing)。 序列基序(Sequential motifs)是拥有相同结构并且其名称结尾的数字不同的节点,它们被折叠进一个单独的节点块(stack)中。对长序列网络来说,序列折叠极大地简化了视图,对于已层叠的节点,双击会展开序列。

一个节点序列的折叠视图。 视图的一小块, 双击后展开。

最后,针对易读性的最后一点要说到的是,可视化为常节点和摘要节点使用了特别的图标,总结起来有下面这些节点符号:

交互

通过平移和缩放来导航图表,点击和拖动用于平移,滚动手势用于缩放。双击一个节点或点击其+按钮来展开代表一组操作的名称域。右下角有一个小地图可以在缩放和平移时方便的改变当前视角。

要关闭一个打开的节点,再次双击它或点击它的-按钮,你也可以只点击一次来选中一个节点,节点的颜色会加深,并且会看到节点的详情,其连接到的节点会在可视化右上角的详情卡片显现。

TensorBoaed 提供一些方法来改变 graph 的可视布局。这不会改变计算但是会使网络结构更清晰。通过右键节点或者点击节点信息卡的底部按钮,你可以对布局作出以下改变:

  • 节点可以在主图与附属区域之间被移动
  • 一列节点可以被分开,也可以被重新组合

选择对于 high-degree 节点的理解也很有帮助,选择任意节点,则与它的其余连接相应的节点也会选中,这使得在进行例如查看哪一个节点是否已保存等操作时非常容易。

点击详情卡片中的一个节点名称时会选中该节点,必要的话,视角会自动平移以使该节点可见。

最后,使用图例上方的颜色菜单,你可以给你的图表选择两个颜色方案。默认的结构视图下,当两个 high-level 节点颜色一样时,其会以相同的彩虹色彩出现,而结构唯一的节点颜色是灰色。还有一个视图则展示了不同的操作运行于什么设备之上。名称域被恰当的根据其中的操作节点的设备片件来着色。

下图是一张真实图表的图解:

张量 shape 信息

当序列化的 GraphDef 包含张量 shapes,图可视化工具给边加上张量维数的标签,边的粗细反映出张量的 size。为了在 GraphDef 中包括张量的信息,传递实际的图(见 sess.graph)到 FileWriter 中当序列化图时。下图展示了带有张量 shape 的 CIFAR-10 模型。

运行时间统计

收集运行元数据经常是有用的,例如总内存使用,总计算时间,和节点张量shapes。下面的代码是train 和 test 修正的 simple MNIST tutorial 一部分。源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Train the model, and also write summaries.
# Every 10th step, measure test-set accuracy, and write test summaries
# All other steps, run train_step on training data, & add training summaries

def feed_dict(train):
"""Make a TensorFlow feed_dict: maps data onto Tensor placeholders."""
if train or FLAGS.fake_data:
xs, ys = mnist.train.next_batch(100, fake_data=FLAGS.fake_data)
k = FLAGS.dropout
else:
xs, ys = mnist.test.images, mnist.test.labels
k = 1.0
return {x: xs, y_: ys, keep_prob: k}

for i in range(FLAGS.max_steps):
if i % 10 == 0: # Record summaries and test-set accuracy
summary, acc = sess.run([merged, accuracy], feed_dict=feed_dict(False))
test_writer.add_summary(summary, i)
print('Accuracy at step %s: %s' % (i, acc))
else: # Record train set summaries, and train
if i % 100 == 99: # Record execution stats
run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
run_metadata = tf.RunMetadata()
summary, _ = sess.run([merged, train_step],
feed_dict=feed_dict(True),
options=run_options,
run_metadata=run_metadata)
train_writer.add_run_metadata(run_metadata, 'step%d' % i)
train_writer.add_summary(summary, i)
print('Adding run metadata for', i)
else: # Record a summary
summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True))
train_writer.add_summary(summary, i)

每运行100步,在99步时记录运行时间统计。

当你运行 tensorboard 并到 Graph 页时,你将看到选项 Session runs,带有运行元数据的一些时间步。选择一个,你将会看到在这步中的网络快照,并剔除没用的节点。在左边的控制台,你将用总内存或总计算时间给节点加上颜色。另外,点击节点将会展示精确的总内存,计算时间和张量输出 sizes。

分享到