TensorFlow 的可视化工具TensorBoard

TensorBoard 是 TensorFlow 提供的实用工具(utility),可以图形化的显示 computational graph。
TensorBoard 是 TensorFlow提供的一组可视化工具(a suite of visualization tools),可以帮助开发者方便的理解、调试、优化TensorFlow 程序。

更多:TensorFlow

第07课:TensorFlow 的可视化

TensorFlow 有非常完善的可视化工具,它的名字叫 TensorBoard。TensorBoard 可以帮助我们更好的理解、调试和优化我们的模型。

这里默认大家已经看完了前面几节课,对 TensorFlow 的variables、placeholder 以及卷积神经网络的实现等知识点有一定了解。

一、TensorBoard 的安装

1,安装 tensorboard:
sudo pip install tensorboard

` 注意,需要用管理员权限,系统会自动安装 TensorBoard,如果是用 Python3,命令是:pip3 install tensorboard

2,运行tensorboard:
tensorboard --logdir=path/to/log-directory

这里的 logdir 是指 tf.summary.FileWriter 写 log 文件的文件夹路径,TensorBoard 会从 logdir 这个文件夹中的日志文件分析相关执行过程,并将结果展示出来。

在浏览器中输入:http://127.0.0.1:6006/ 就能看到 Tensorboard 的 web 界面

Tensorboard 界面

这里,页面告诉我们,目前还没有事件数据。后面我们写好相应的代码,然后跑一遍模型,就会有数据了。

二、TensorBoard 的几大模块

Tensorboard 的可视化模块:

  • Scalars:记录标量曲线。例如准确率、损失率、权重和偏置等变化。在代码中用 tf.summary.scalar() 进行收集。
  • Images:记录数据图像。对于图像分类问题,可以将输入或者训练过程中的图片展示出来。在代码中用 tf.summary.image() 定义需要在这个选项卡中展示的数据(直接绘制成图像展示),默认是绘制3张图片。
  • Audio:记录音频数据。
  • Graphs:记录 TensorFlow 的数据流图。需要在程序中用 with tf.namescope() 或者 with tf.namescope() as scope 来收集。
  • Distributions:数据分布图。可以用来显示激活前和激活后数据的分布情况,辅助设计分析。
  • Histograms:数据柱状图。在代码中用 tf.summary.histogram() 收集。
  • Embeddings:用于文本分析,展示词向量的投影分布(例如 word2vec )

三、案例:卷积神经网络的可视化

这里使用三种类型的数据:

with tf.name_scope(‘XXXX’):记录的图类型数据,可以显示出模型的组成 tf.summary.scalar(‘xxxx’, xxxx):显示一些标量的曲线 y = tf.summary.histogram(‘yyy’, yyy):显示一些数据的柱状图

编码实现:

0,前期处理

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plot
from tensorflow.examples.tutorials.mnist import input_data 
import pandas as pd

#1 加载数据集
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv").values

#2 把图片数据取出来,进行处理
x_train = train.iloc[:,1:].values
x_train = x_train.astype(np.float)

#3 给到的图片的灰度数值在0~255,这里将图片的信息控制在0~1之间
x_train = np.multiply(x_train, 1.0 / 255.0)

#4 计算图片的长和高,下面会用到
image_size = x_train.shape[1]
image_width = image_height = np.ceil(np.sqrt(image_size)).astype(np.uint8)

print('数据样本大小: (%g, %g)' % x_train.shape)
print ('图片的维度大小 => {0}'.format(image_size))
print ('图片长 => {0}\n图片高 => {1}'.format(image_width,image_height))

# 5把数据集的标签结果取出来
labels_flat = train[[0]].values.ravel()
labels_count = np.unique(labels_flat).shape[0]

#写一个对Label进行One_Hot处理的函数
def dense_to_one_hot(labels_dense, num_classes):
    num_labels = labels_dense.shape[0]
    index_offset = np.arange(num_labels) * num_classes
    labels_one_hot = np.zeros((num_labels, num_classes))
    labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
    return labels_one_hot

# 6 对Label进行One_Hot处理
labels = dense_to_one_hot(labels_flat, labels_count)
labels = labels.astype(np.uint8)

print('标签({0[0]},{0[1]})'.format(labels.shape))
print ('图片标签举例:[{0}] => {1}'.format(25,labels[25]))

#7 把训练数据分为训练图片集和验证图片集

VALIDATION_SIZE = 2000

train_images = x_train[VALIDATION_SIZE:]
train_labels = labels[VALIDATION_SIZE:]

validation_images = x_train[:VALIDATION_SIZE]
validation_labels = labels[:VALIDATION_SIZE]

#8 设置批次大小,求得批次数量
batch_size = 100
n_batch = len(train_images)/batch_size

1,设置输入值

# 9 定义两个placeholder,用来承载数据,因为每个图片,都是一个784维的数据,所以我们的x是784列;
#   因为要把图片识别为0-9的10个数字,也就是有10个标签,所以y是10列
# 一、收集输入值
with tf.name_scope("input"):
    x = tf.placeholder(tf.float32,[None,784],name="x-input")
    y = tf.placeholder(tf.float32,[None,10],name="y-input")


# 10 定义几个处理的函数
def weight_variable(shape):
    # 初始化权重,正态分布 标准方差为0.1
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

def bias_variable(shape):
    # 初始化偏置值,设为非零避免死神经元
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

    #对TensorFlow的2D卷积进行封装
def conv2d(x, W):
    # 卷积不改变输入的shape
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

    #对TensorFlow的池化进行封装
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                              strides=[1, 2, 2, 1], padding='SAME')


# 11 把输入变换成一个4d的张量,第二三个对应的是图片的长和宽,第四个参数对应的颜色
x_image = tf.reshape(x, [-1, 28, 28, 1])

2,收集第一个卷积层

# ai8py.com
# 二、收集第一个卷积层
# 12 计算32个特征,每3*3patch,第一二个参数指的是patch的size,第三个参数是输入的channels,第四个参数是输出的channels
with tf.name_scope('first_layer_weights'):
    W_conv1 = weight_variable([3,3, 1, 32])
    w_hist1 = tf.summary.histogram('first_layer_weights', W_conv1)

# 13 偏差的shape应该和输出的shape一致,所以也是32
with tf.name_scope('first_layer_bias'):
    b_conv1 = bias_variable([32])
    b_hist1 = tf.summary.histogram('first_layer_biases', b_conv1)

# 28*28的图片卷积时步长为1,随意卷积后大小不变,按2*2最大值池化,相当于从2*2块中提取一个最大值,
# 所以池化后大小为[28/2,28/2] = [14,14],第二次池化后为[14/2,14/2] = [7,7]

# 14 对数据做卷积操作
with tf.name_scope('first_layer_output'):
    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
    l1_hist = tf.summary.histogram('l1', h_conv1)

3,收集第一个池化层

# 三、收集第一个池化层
# 15 对结果做池化,max_pool_2x2之后,图片变成14*14
with tf.name_scope('first_pool'):
    h_pool1 = max_pool_2x2(h_conv1)

4,收集第二个卷积层

#四、收集第二个卷积层
# 16 在以前的基础上,生成了64个特征
with tf.name_scope('second_layer_weights'):
    W_conv2 = weight_variable([6, 6, 32, 64])
    w_hist2 = tf.summary.histogram('second_layer_weights', W_conv2)
with tf.name_scope('second_layer_bias'):
    b_conv2 = bias_variable([64]) 
    b_hist2 = tf.summary.histogram('second_layer_biases', b_conv2)
with tf.name_scope('second_layer_output'):
    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
    l2_hist = tf.summary.histogram('l2', h_conv2)

5,收集第二个池化层

#五、收集第二个池化层
# 17 max_pool_2x2之后,图片变成7*7
with tf.name_scope('second_pool'):

    h_pool2 = max_pool_2x2(h_conv2)
    h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])

6,收集全连接层

#六、收集全连接层
# 18 构造一个全连接的神经网络,1024个神经元

with tf.name_scope('FC'):

    W_fc1 = weight_variable([7 * 7 * 64, 100])
    b_fc1 = bias_variable([100])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

7,收集 Dropout

#七、收集Dropout
# 19 做Dropout操作
with tf.name_scope('keep_prob'):

    keep_prob = tf.placeholder(tf.float32)
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

8,收集结果

#八、收集输出层
# 20 把1024个神经元的输入变为一个10维输出
with tf.name_scope('out_put'):

    W_fc2 = weight_variable([100, 10])
    b_fc2 = bias_variable([10])
    y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

9,收集损失函数

#九、收集损失函数
# 21 创建损失函数,以交叉熵的平均值为衡量
with tf.name_scope('loss'): 

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y, logits =y_conv ))
    tf.summary.scalar('loss_s', loss)

10,收集训练模块

#十、收集训练模块
# 22  用梯度下降法优化参数
with tf.name_scope('train'):

    train_step_1 = tf.train.AdadeltaOptimizer(learning_rate=0.1).minimize(loss)

11,收集准确度

#十一、收集准确度
# 23 计算准确度
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_conv,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
tf.summary.scalar('accuracy', accuracy)

# 24 设置保存模型的文件名参数
global_step = tf.Variable(0,name = 'global_step', trainable = False)
saver = tf.train.Saver()

# 25 初始化变量
init = tf.global_variables_initializer()

12,获取所有汇总操作

merged = tf.summary.merge_all()

13,运行

with tf.Session() as sess:
    # 26初始化
    sess.run(init)

    # 设置tensorboard的Summary
    writer = tf.summary.FileWriter("logs/",sess.graph)

    #这是载入以前训练好的模型的语句,有需要才用,注意把文件名改成成绩比较好的周期
    #saver.restore(sess,"model.ckpt-12")

    # 为了不等太久,这里只迭代10周期
    for epoch in range(1,10):

        for batch in range(n_batch):
            # 27 每次取出一个数据块进行训练
            batch_x = train_images[(batch)*batch_size:(batch+1)*batch_size]
            batch_y = train_labels[(batch)*batch_size:(batch+1)*batch_size]

            # 28 【重要】 这是最终运行整个训练模型的语句
            result=sess.run([merged,train_step_1],feed_dict = {x:batch_x,y:batch_y,keep_prob: 0.5})

            # 加入收集的记录
            summary=result[0]
            writer.add_summary(summary,batch*epoch)


        # 29 每个周期计算一次准确度
        accuracy_n = sess.run(accuracy,feed_dict={ x: validation_images, y: validation_labels, keep_prob: 1.0})

        print ("第" + str(epoch+1)+"轮,准确度为:"+str(accuracy_n))

        # 30 保存训练出来的模型,这样不用每次都从头开始训练了
        global_step.assign(epoch).eval()
        saver.save(sess,"model.ckpt",global_step = global_step)

四、结果示例:

标量数据可视化
模型可视化
数据分布可视化
参数可视化

发表评论

电子邮件地址不会被公开。 必填项已用*标注