[TensorFlow]使用Tensorboard实现神经网络可视化

来源:互联网 发布:兰州大学网络教育入口 编辑:程序博客网 时间:2024/06/06 02:53

主旨

可视化是深度学习神经网络开发、调试、应用中极为重要的手段。Tensorboard是Tensorflow提供的一个可视化工具,本文通过实际代码实验的方式说明使用TensorBoard实现记录变量,实现可视化调试的目的。

源代码

我的GitHub中TF_Graph项目, singleNerualNode.py

网络结构

为了简化情况,实验中使用单层神经网络,网络结构定义见笔者前一篇文章 [TensorFlow]理解Tensorboard Graph“案例1:单个神经元”

TensorBoard基本调用方法

  • 网络结构定义中将所有输出到tf.summary的变量合并到一个Tensor
merged = tf.summary.merge_all()
  • 创建Writer
  log_path =  "tf_writer"  writer = tf.summary.FileWriter(log_path, sess.graph)
  • 在训练中计算merged Tensor,并输出到writer
  for iterIdx in range(iterationNumber):    sess.run(train_step, feed_dict={inputTensor: inputData, labelTensor:labels})    summary = sess.run(merged, feed_dict={inputTensor: inputData, labelTensor:labels})    writer.add_summary(summary, iterIdx)    #flush to disk every 50 iteration    if iterIdx % 50 == 0:        writer.flush()  writer.close()
  • 启动TensorBoard,在shell输入如下命令

    tensorboard –logdir tf_writer
    注:’tf_writer’是我的log_path, 实际使用中根据存储Log的位置调整

  • 从浏览器中访问
    打开浏览器访问http://192.168.1.100:6006/,其中’192.168.1.100’是运行Tensorboard的计算机IP地址,可以是本机,也可以是网络上的服务器,能访问到就行。

标量(Scalar)的输出

区别于矩阵和向量,标量可以认为只有1个维度的数值量。

在神经网络中,损失函数的值、模型预测准确率等都是典型的标量。如下是计算损失函数和模型预测准确率的代码。

  with tf.name_scope('evaluation'):    loss = tf.nn.l2_loss(a - labels, name='L2Loss') / batchSize    threshold = 0.5     binary_outputs = a >= threshold    binary_labels = labels >= threshold    correct_item = tf.equal(binary_outputs, binary_labels)    accuracy = tf.reduce_mean(tf.cast(correct_item, tf.float32))

对于这些变量,我们最典型的需求是知道每一轮模型训练迭代中,其朝着哪个方向变化,是否达到收敛状态。使用Tensorboard,只要添加以下代码就可以实现

  tf.summary.scalar('L2Loss',loss)  tf.summary.scalar('Accuracy', accuracy)

在Tensorboard中看到的结果如下,Accuracy和L2 Loss分别记录在两张图表中,每张图的横坐标表示迭代序号(第几次训练),纵坐标就是我们添加的标量结果
这里写图片描述

以Accuracy为例,放大观察
这里写图片描述

Tensorboard会记录每个点的名称、平滑后取值、原始值、Step(迭代序号)、时间戳和相对于训练开始过了多长时间。这些信息对于可视化的观察模型收敛情况非常有帮助。

多维张量(Tensor)的输出

标量(scalar)在Tensor Flow的神经网络中只占很少一部分,大部分变量是多维张量,即Tensor。由于一个Tensor有多个维度,无法像标量一样直接输出成曲线,在可视化时可以有以下几种方法:

  1. 将Tensor转化为标量输出
  2. 输出Tensor的分布直方图
  3. 如果Tensor本身是图形(即以[batch, height, weight, channel]格式的图片),以图片形式输出

第一种,在TensorBoard的官方教程中给出了清晰的示意代码。给定一个Tensor,如下函数从均值、标准差、最大值、最小值等多个角度转化为标量,从而可视化。由于标量的可视化效果前一节已经展示过了,这里不在重复。

def variable_summaries(var):  """Attach a lot of summaries to a Tensor (for TensorBoard visualization)."""  with tf.name_scope('summaries'):    mean = tf.reduce_mean(var)    tf.summary.scalar('mean', mean)    with tf.name_scope('stddev'):      stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))    tf.summary.scalar('stddev', stddev)    tf.summary.scalar('max', tf.reduce_max(var))    tf.summary.scalar('min', tf.reduce_min(var))

第二种,以直方图输出,输出方法非常简单,按照下列代码的方式调用tf.summary.histogram即可

  with tf.name_scope('Nerual_Node'):    W = tf.Variable(tf.random_normal([numberOfInputDims, 1]), name='weights')    tf.summary.histogram('weights', W)    b = tf.Variable(tf.zeros([1]), name='biases')    tf.summary.histogram('biases', b)

问题的难点在于如何理解直方图的输出,直方图的输出形式如下
这里写图片描述

放大其中bias这张图
这里写图片描述

这张图垂直于屏幕的方向,即高亮的一行显示822则个数据所在的坐标轴,是迭代次数序号。随着训练迭代次数由0到最大迭代次数(这里设定为1000)训练,bias的分布由远及近画出来。

关键问题是“bias的分布”指的是什么,根据代码bias本身定义为1维Tensor:b = tf.Variable(tf.zeros([1]), name=’biases’),一个Batch定义为1000,那么b可以视为具有1000个元素的一维数组,上图每个横截面给出的是这1000个元素的概率分布。

带着这个结论,接下来考察更复杂的多维Tensor的直方图:weight
这里写图片描述
weight本身定义维2*1 Tensor,每个batch定义为1000个样本
W = tf.Variable(tf.random_normal([numberOfInputDims, 1]), name='weights')
则直方图代表的是总数为2*1*1000个取值的分布。

我们将W设计维2*1,是为了保存两个输入节点分别的权重:w_1和w_2。在上述直方图分布中,确实可以清晰的看到W的分布呈现双峰分布,这两个峰分别对应w_1和w_2。随着训练次数的增加,w_1和w_2相距越来越远,这和训练目标是实现线性分类是吻合的。

第三种,以图形形式输出,在TensorFlow API中有详细描述,由于这次我们选择的简单神经网络中不具备这样格式的Tensor,暂时无法通过例子说明。API文档链接如下
https://www.tensorflow.org/versions/master/api_docs/python/tf/summary/image

Embedding

除了前文描述的标量和Tensor输出之外,可视化还包括观察大量数据的分布。这里大量数据可以是输入、输出数据,也可以是网络中的任意参数。

Google对此有一篇专门的论文,其中Introduction对于Embedding的定义和作用有清晰的描述,笔者尝试翻译如下

embedding是从输入数据点到欧式空间中点的映射,为了理解模型的行为特征,机器学习的研发人员经常需要探索某个特定的Embedding。例如做音乐推荐系统的工程师创建了一个歌曲的embedding,他可能需要验证”Stairway to Heaven”这支歌曲最近的邻居包括“Whole Lotta Love”但不包括”Let it Go”. 对于这样的用户,从Embedding的几何结构获得理解就很关键。

具体到我们的案例,假定我想知道输入数据的几何分布,使用如下代码实现。

from tensorflow.contrib.tensorboard.plugins import projector  ....  embedding_var = tf.Variable(inputData, 'data_embeding')  config = projector.ProjectorConfig()  embedding = config.embeddings.add()  embedding.tensor_name = embedding_var.name  embedding.metadata_path = 'label.csv'  projector.visualize_embeddings(tf.summary.FileWriter(log_path), config)

代码中inputData是1000*2的Tensor,表示1000个二维平面上的点。label.csv是包含了这1000个数据标签的文件,格式见如下文件
https://github.com/wangyaobupt/TF_Graph/blob/master/label.csv

Embedding还必须依赖于模型的保存,在定义网络结构中,需要定义saver如下

  all_vars = tf.global_variables()  saver = tf.train.Saver(all_vars)

在模型训练中,必须保存训练结果

  for iterIdx in range(iterationNumber):    sess.run(train_step, feed_dict={inputTensor: inputData, labelTensor:labels})    .....    saver.save(sess, model_path)

上述工作完成后,运行得到如下图形
这里写图片描述

从图形左侧逐一解释,首先左上部分要选择数据和颜色,我们整个网络中只添加了一个Embedding Tensor,因此不用特殊选定,颜色算则Label即可,即根据label文件不同的标签标识颜色。

左下部有三张选项卡,s_TNE/PCA/Custom,默认为PCA。这里使用PCA是为了把高维Tensor降低到3维,以方便可视化。但我们此次实验的数据,扣除表示batch的维度,只有2维,因此PCA的输出就是数据的X、Y坐标,同时不需要显示Z轴。

右侧是实际图形,图中可以清晰的看到训练数据的线性可分性质。

由于Tensorflow在Embedding的文档本身较少,笔者写作这一节内容时参考了大量网络资料,特别感谢以下这Link的回答者Ehsan和Albert X.W.

  • http://stackoverflow.com/questions/40849116/how-to-use-tensorboard-embedding-projector
2 0
原创粉丝点击