Tensorflow: 可视化

import tensorflow as tf

将运行过程中的信息汇总成一个序列化的 Summary protobuf 对象, 最后通过 tf.summary.FileWriter 类写入到磁盘.

  • tf.summary.FileWriter 类
''' __init__() 作用: 将图的汇总信息写入到磁盘的类, 写入磁盘的方式为异步, 因此不会降低训练的速度. 参数: logdir: (must)事件写入的文件位置; graph: 写入对应的Graph类, 一般使用'sess.graph'获取会话Session对应的图; max_queue: 整数, 待写入的队列大小; flush_secs: 将事件刷新到磁盘的时间间隔; '''
with tf.Graph().as_default():
    with tf.Session() as sess:
        summary_writer = tf.summary.FileWriter("../log/", graph=sess.graph)
  • tf.summary.merge_all()
''' 作用: 收集合并默认图中所有的summary. 参数: key: 'GraphKey', 用来收集summary; 默认为_ops.GraphKeys.SUMMARIES 输出: 如果没有创建summary, 结果为空, 否则返回一个dtype为string的Tensor, 内容是序列化的字符串, 包含merge合并后的Summary protocol buffer. '''
  • tf.summary.scalar()
''' 作用: 输出一个包含单个标量值的summary协议缓冲区. 参数: name: string/Tensor, 字符串或已经创建的表示summary的Tensor, 为summary的名称(标签), 也是此Op的名称; tensor: Tensor, 要记录的包含单个标量值的Tensor; collections: 将此Op添加到图中collection指定的key值中. 输出: Tensor, 类型为string, 包含summary协议缓冲区的信息. '''
  • tf.summary.image()
''' 作用: 输出一个包含图像的summary协议缓冲区. 参数: name: string/Tensor, 字符串或已经创建的表示summary的Tensor, 为summary的名称(标签), 也是此Op的名称; tensor: 要记录的图像Tensor, 格式必须为4-D的uint8或float32, shape中元素意义为[batch_size,height, width, channels], channels的值为{1: 灰度图, 3: RGB图, 4: RGBA图}; max_outputs: (不明); collections: 将此Op添加到图中collection指定的key值中. 输出: Tensor, 类型为string, 包含summary协议缓冲区的信息. '''
  • tf.summary.histogram()
''' 作用: 输出一个包含直方图的summary协议缓冲区. 参数: name: string/Tensor, 字符串或已经创建的表示summary的Tensor, 为summary的名称(标签), 也是此Op的名称; values: Tensor, 任何shape, 用来构建直方图; collections: 将此Op添加到图中collection指定的key值中. 输出: Tensor, 类型为string, 包含summary协议缓冲区的信息. '''
  • tf.summary.audio()
''' 作用: 输出一个包含音频的summary协议缓冲区. 参数: name: string/Tensor, 字符串或已经创建的表示summary的Tensor, 为summary的名称(标签), 也是此Op的名称; tensor: 要记录的图像Tensor, 格式为: 1. 3-D的float32, shape中元素意义为[batch_size,frames, channels], 2. 2-D的float32, shape中元素意义为[batch_size, frames]; sample_rate: Tensor, float32标量, (不明); max_outputs: (不明); collections: 将此Op添加到图中collection指定的key值中. 输出: Tensor, 类型为string, 包含summary协议缓冲区的信息. '''

FileWriter 类的方法总结:

  • tf.summary.FileWriter.add_summary()
''' 作用: 将一个协议缓冲区添加到此Writer中, 并写入事件到文件中. 参数: summary: (must)一个协议缓冲区(Summary protocol buffer), 值为序列化的string, 一般使用str = sess.run(tf.summary.merge_all())的结果作为输入; global_step: 数字, 记录全局步数的量 '''
  • tf.summary.FileWriter.flush()
''' 作用: 手动将事件写入到磁盘中 '''
  • tf.summary.FileWriter.close()
''' 作用: 关闭该Writer '''

使用MNIST数据构建一个简单的DNN网络, 测试Tensorboard功能

# -*- coding: utf-8 -*-

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

FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_string("data_dir", "../../data/MNIST_data/", "Mnist data directory.")
tf.app.flags.DEFINE_string("log_dir", "../log/MNIST_SUMMARY/", "Summary log directory.")
tf.app.flags.DEFINE_integer("batch_size", 100, "Batch size.")
tf.app.flags.DEFINE_integer("image_size", mnist.IMAGE_PIXELS, "Numbers of pixels in one image.")
tf.app.flags.DEFINE_integer("hidden1_size", 128, "First hidden layer's size.")
tf.app.flags.DEFINE_integer("hidden2_size", 32, "Second hidden layer's size.")
tf.app.flags.DEFINE_integer("num_classes", 10, "Number of label's classes.")
tf.app.flags.DEFINE_integer("max_steps", 2000, "Max mini-batches training steps.")
tf.app.flags.DEFINE_float("learning_rate", 0.01, "Learning rate.")

def main(*args, **kwargs):
    data = read_data_sets(FLAGS.data_dir)

    with tf.Graph().as_default():
        images_placeholder = tf.placeholder(tf.float32, shape=(FLAGS.batch_size, FLAGS.image_size))
        labels_placeholder = tf.placeholder(tf.int32, shape=(FLAGS.batch_size))

        with tf.variable_scope("hidden1"):
            weights = tf.get_variable("weights", shape=[FLAGS.image_size, FLAGS.hidden1_size], initializer=tf.truncated_normal_initializer(stddev=1.0/math.sqrt(float(FLAGS.image_size))))
            biases = tf.get_variable("biases", shape=[FLAGS.hidden1_size], initializer=tf.zeros_initializer())

            hidden1 = tf.nn.relu(tf.matmul(images_placeholder, weights) + biases, name="relu")
            tf.summary.histogram("hidden1", hidden1)
        with tf.variable_scope("hidden2"):
            weights = tf.get_variable("weights", shape=[FLAGS.hidden1_size, FLAGS.hidden2_size], initializer=tf.truncated_normal_initializer(stddev=1.0 / math.sqrt(float(FLAGS.hidden1_size))))
            biases = tf.get_variable("biases", shape=[FLAGS.hidden2_size], initializer=tf.zeros_initializer())

            hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases, name="relu")
            tf.summary.histogram("hidden2", hidden2)
        with tf.variable_scope("softmax_linear"):
            weights = tf.get_variable("weights", shape=[FLAGS.hidden2_size, FLAGS.num_classes], initializer=tf.truncated_normal_initializer(stddev=1.0 / math.sqrt(float(FLAGS.hidden2_size))))
            biases = tf.get_variable("biases", shape=[FLAGS.num_classes], initializer=tf.zeros_initializer())

            logits = tf.matmul(hidden2, weights) + biases
            tf.summary.histogram("logits", logits)

        labels = tf.to_int64(labels_placeholder)
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits, name="xentropy")
        loss = tf.reduce_mean(cross_entropy, name="xentropy_mean")

        tf.summary.scalar("loss", loss)
        optimizer = tf.train.GradientDescentOptimizer(FLAGS.learning_rate)
        global_step = tf.Variable(0, name="global_step", trainable=False)
        train_op = optimizer.minimize(loss, global_step=global_step)

        correct = tf.nn.in_top_k(logits, labels, 1)
        eval_correct = tf.reduce_sum(tf.cast(correct, tf.int32))
        tf.summary.histogram("correct", tf.cast(correct, tf.int32))
        tf.summary.scalar("correct_evaluate", eval_correct)

        summary = tf.summary.merge_all()

        with tf.Session() as sess:
            tf.global_variables_initializer().run()

            summary_writer = tf.summary.FileWriter(FLAGS.log_dir, graph=sess.graph)

            for step in range(FLAGS.max_steps):
                images_feed, labels_feed = data.train.next_batch(FLAGS.batch_size)
                images_data = tf.reshape(images_feed, shape=[FLAGS.batch_size, 28, 28, 1], name="real_images")
                feed_dict = {
                    images_placeholder: images_feed,
                    labels_placeholder: labels_feed,
                }
                _, loss_value = sess.run([train_op, loss], feed_dict=feed_dict)

                if step % 100 == 0:
                    summary_str = sess.run(summary, feed_dict=feed_dict)
                    summary_writer.add_summary(summary_str, global_step=step)

                    summary_str = sess.run(tf.summary.image("images", images_data))
                    summary_writer.add_summary(summary_str, global_step=step)

                    summary_writer.flush()


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

从代码中看出:

  1. loss, eval_correct两个Tensor使用summary.scalar记录;
  2. hidden1, hidden2, logits, correct使用summary.histogram直方图记录;
  3. images_feed即每次批量图片数据, 规整为[batch_size, height, width, channel]格式后, 使用summary.image每隔100步batch记录一次.
  1. 首先能在GRAPHS栏目下, 能看到整个网络结构的可视化:

  2. 在SCALARS栏目下, 有summary.scalar的记录:

    打开记录的lossTensor:

    可以看到loss的值随着迭代次数step增加的变化情况

  3. 在HISTOGRAMS栏目下, 能看到summary.histograms的记录:

    这里打开的是输出层softmax层在激活函数之前的数值logits的情况, 可以看出概率密度图的结构, 即在某次迭代过程中执行时, 就画一个在当时的这个Tensor的概率密度分布图, 并把若干张在纵轴上叠加起来. 横轴表示的是值的取值方位, 对应的纵轴为该值的分布密度(?).

  4. 在IMAGES栏目下, 能看到summary.image记录的图像:
    这里的summary.image()方法中max_outputs=3(默认), 因此虽然batch_size=10, 每次只记录3张图片.

你可能感兴趣的:(可视化,tensorflow)