Tensorflow基础:TensorBoard可视化

为了更好的管理、调试和优化神经网络的训练过程,Tensorflow提供了一个可视化工具TensorBoard。TensorBoard可以有效地展示Tensorflow在运行过程中的计算图、各种指标随着时间的变化趋势以及训练中使用到的图像等信息。

TensorBoard简介

TensorBoard是Tensorflow的可视化工具,它可以通过Tensorflow程序运行过程中输出的日志文件可视化Tensorflow程序的运行状态。TensorBoard和Tensorflow程序跑在不同的进程中,TensorBoard会自动读取最新的Tensorflow日志文件,并呈现当前Tensorflow程序运行的最新状态。
一下代码展示了一个简单的Tensorflow程序,在这个程序中完成了TensorBoard日志输出的功能:

import tensorflow as tf


# 定义一个简单的计算图,实现向量加法的操作
input1 = tf.constant([1.0, 2.0, 3.0], name='input1')
input2 = tf.Variable(tf.random_uniform([3]), name='input2')
output = tf.add_n([input1, input2], name='add')

# 生成一个写日志的writer,并将当前的Tensorflow计算图写入日志。Tensorflow提供了多种
# 写日志文件的API
writer = tf.summary.FileWriter('E://dogs', tf.get_default_graph())
writer.close()

运行以上代码,将计算图写入日志。
TensorBoard不需要额外的安装,在Tensorflow安装完成时,Tensorboard会被自动安装。在终端(cmd)运行下面的命令可以启动TensorBoard:

这里写图片描述

在浏览器输入上述网址,便可得到可视化结果:
这里写图片描述

Tensorflow计算图可视化

上图给出了一个Tensorflow计算图的可视化效果图。然而,从Tensorflow可视化结果中可以获取的信息远不止上图所示。这一节将详细介绍如何更好地利用Tensorflow计算图的可视化结果,没有经过整理得到的可视化效果图并不能帮助很好地理解神经网络模型的结构。

命名空间与TensorBoard图上节点

为了更好地组织可视化效果图中的计算节点,TensorBoard支持通过Tensorflow命名空间来整理可视化效果图上的节点。在TensorBoard的默认视图中,Tensorflow计算图中同一个命名空间下的所有节点会被缩略成一个节点,只有顶层命名空间中的节点才会被显示在Tensorflow可视化效果图上。tf.variable_scope函数和tf.name_scope函数提供了命名空间管理的功能。这两个函数在大部分情况下是等价的,唯一的区别是使用tf.get_variable时。以下代码简单地说明了这两个函数的区别。

import tensorflow as tf

with tf.variable_scope('foo'):
    # 在命名空间foo下获取变量“bar”,于是得到的变量名称为“foo/bar”
    a = tf.get_variable("bar", [1])
    print(a.name)

with tf.variable_scope("bar"):
    # 在命名空间bar下获取变量“bar”,于是得到的变量名称为“bar/bar”。此时变量
    # “bar/bar”和“foo/bar”并不冲突,于是可以正常运行。
    b = tf.get_variable("bar", [1])
    print(b.name)

with tf.name_scope("a"):
    # 使用tf.Variable函数生成变量会受到tf.name_scope影响,于是这个变量的名称为“a/Variable”
    a = tf.Variable([1])
    print(a.name)

    # tf.get_variable函数不受tf.name_scope函数的影响,于是变量并不在a这个命名空间中
    a = tf.get_variable("b", [1])
    print(a.name)

with tf.name_scope("b"):
    # 报错:重复声明
    tf.get_variable("b", [1])

通过对命名空间,可以改进上一节中向量相加的样例代码,使得可视化得到的效果图更加清晰:

import tensorflow as tf

with tf.name_scope("input1"):
    input1 = tf.constant([1.0, 2.0, 3.0], name="input1")

with tf.name_scope("input2"):
    input2 = tf.Variable(tf.random_uniform([3]), name='input2')

output = tf.add_n([input1, input2], name='add')

writer = tf.summary.FileWriter("E://dog", tf.get_default_graph())
writer.close()

这里写图片描述

我们以MNIST最佳实践为例,以下代码给出了改造后的mnist_train.py程序:

# _*_ coding: utf-8 _*_
import os

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 加载mnist_inference.py中定义的常量和前向传播的函数
import mnist_inference

# 配置神经网络的参数
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99
REGULARAZTION_RATE = 0.0001
TRAIN_STEPS = 30000
MOVING_AVERAGE_DECAY = 0.99

MODEL_SAVE_PATH = "./model/"
MODEL_NAME = "model2.ckpt"

def train(mnist):
    with tf.name_scope('input'):
        x = tf.placeholder(tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input')
        y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input')



    regularizer = tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)

    y = mnist_inference.inference(x, regularizer)

    global_step = tf.Variable(0, trainable=False)

    with tf.name_scope("moving_average"):
        variable_average = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
        variable_average_op = variable_average.apply(
            tf.trainable_variables())

    with tf.name_scope("loss_function"):
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=tf.argmax(y_, 1), logits=y)
        cross_entropy_mean = tf.reduce_mean(cross_entropy)

        loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))

    with tf.name_scope("train_step"):
        learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,
                                                   global_step=global_step,
                                                   decay_steps=mnist.train.num_examples / BATCH_SIZE,
                                                   decay_rate=LEARNING_RATE_DECAY)
        train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)

        with tf.control_dependencies([train_step, variable_average_op]):
            train_op = tf.no_op(name='train')

    saver = tf.train.Saver()
    with tf.Session() as sess:
        tf.global_variables_initializer().run()

        for i in range(TRAIN_STEPS):
            xs, ys = mnist.train.next_batch(BATCH_SIZE)
            _, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
            if i % 1000 == 0:
                print("After %d training steps, loss on training"
                      "batch is %g" % (step, loss_value))
                saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
        writer = tf.summary.FileWriter('E://Mnist', tf.get_default_graph())
        writer.close()

def main(argv=None):
    mnist = input_data.read_data_sets("E:\科研\TensorFlow教程\MNIST_data", one_hot=True)
    train(mnist)

if __name__ == '__main__':
    tf.app.run()

得到的计算图为:

这里写图片描述

Tensorflow中部分计算节点会有比较多的依赖关系,如果全部画在一张图上会使可视化得到的效果图非常拥挤。于是TensorBoard将Tensorflow计算图分成了主图(Main Graph)和辅助图(Auxiliary nodes)两部分来呈现。
除了自动方式,TensorBoard也支持手工的方式来调整可视化结果。右键单击可视化效果图上的节点会弹出一个选项,这个选项可以将节点加入主图或从主图中删除:
这里写图片描述

节点信息

TensorBoard还可以展示Tensorflow计算图上每个节点的基本信息以及运行时消耗的时间和空间。Tensorflow计算节点的运行时间都是非常有用的信息,它可以帮助更加有针对性地优化Tensorflow程序,使得整个程序的运行速度更快。使用TensorBoard可以非常直观地展现所有Tensorflow计算节点在某一次运行时所消耗的时间和内存。
对mnist_train.py神经网络训练部分进行修改,就可以计算运行时间和内存消耗:

    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        writer = tf.summary.FileWriter('E://Mnist4', tf.get_default_graph())
        writer.close()

        for i in range(TRAIN_STEPS):
            xs, ys = mnist.train.next_batch(BATCH_SIZE)

            if i % 1000 == 0:
                # 配置运行时需要记录的信息
                run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
                # 运行时记录运行信息的proto
                run_metadata = tf.RunMetadata()
                _, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys},
                                               options=run_options, run_metadata=run_metadata)
                writer.add_run_metadata(run_metadata, "step%03d" % i)
                print("After %d training steps, loss on training"
                      "batch is %g" % (step, loss_value))
                saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
            else:
                _, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值