由于神经网络由大量的神经元组成,我们使用TensorFlow编写程序,设计神经网络,其实我们往往也不知道神经网络里头具体细节到底做了什么,要人工调试十分困难,我们经常使用绘图工具(matplotlib),绘制训练过程中的Loss、Acc图。训练神经网络可视化是深度学习神经网络开发、调试、应用中极为重要的手段。有了TensorBoard,可以将TensorFlow程序的执行步骤都显示出来,非常直观。
TensorBoard是tensorflow官方推出的可视化工具,通过对Tensoflow程序运行过程中输出的日志文件进行可视化Tensorflow程序的运行状态,它可以将模型训练过程中的参数、调优等各种数据展示出来,包括标量(Scalars)、图片(Images)、音频(Audio)、计算图(Graphs)、数据分布(Distributions)、直方图(Histograms)和潜入向量(Embeddigngs)。
通过Tensorflow开发等深度学习神经网络,代码执行过程是先构建图,再依图喂数据执行训练模型,这样对中间过程的调试不太方便;而且,在训练大型深度学习神经网络时,中间的计算过程大多非常复杂,因此为了理解、调试和优化神经网络,Tensorflow配套提供TensorBoard观察训练过程中的可视。
使用TensorBoard展示数据,需要在执行Tensorflow计算图的过程中,将各种类型的数据(summary protobuf)汇总并记录到日志文件中。然后使用TensorBoard读取这些日志文件,解析数据并生产数据可视化的Web页面,让我们可以在浏览器中观察各种汇总数据。
tf.summary.scalar(‘Loss’, loss) #记录标量
tf.summary.histogram(‘var_name’, var) #变量的直方图
tf.summary.distribution #变量的分布图
tf.summary.image #记录图像
对于多维张量(Tensor)的输出,标量(scalar)在TensorFlow的神经网络中只占很少一部分,大部分变量是多维张量,即Tensor。由于一个Tensor有多个维度,无法像标量一样直接输出成曲线,在可视化时可以有以下几种方法:
首先,先给出未可视化处理的神经网络程序,后面将基于此代码加上可视化内容。
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
#获取所有的数据集
mnist_data = input_data.read_data_sets("/MNIST_data",one_hot=True)
#定义神经网络的参数
in_units = 784
h1_units = 300
#定义输入变量
x = tf.placeholder(dtype=tf.float32,shape=[None,in_units],name='x')
#定义输出变量
y_ = tf.placeholder(dtype=tf.float32,shape=[None,10],name='y_')
w1 = tf.Variable(tf.truncated_normal([in_units,h1_units],stddev=0.1),name='weights1')
b1 = tf.Variable(tf.zeros([h1_units],dtype=tf.float32),name='biases1')
#手写数字0到9,10个
w2 = tf.Variable(tf.truncated_normal([h1_units,10],stddev=0.1),dtype=tf.float32,name='weights2')
b2 = tf.Variable(tf.zeros([10],dtype=tf.float32),name='biases2')
#定义dropout保留的节点数量
keep_prob = tf.placeholder(dtype=tf.float32,name='keep_prob')
#定义前向传播过程
h1 = tf.nn.relu(tf.add(tf.matmul(x,w1),b1))
#使用dropout
h1_drop = tf.nn.dropout(h1,keep_prob)
#定义输出y
y_conv = tf.nn.softmax(tf.matmul(h1_drop,w2)+b2,name='y')
#定义损失函数
loss_func = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1]))
train_step = tf.train.AdagradOptimizer(0.3).minimize(loss_func)
correct_pred = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(3000):
batch_xs,batch_ys = mnist_data.train.next_batch(100)
sess.run(train_step, feed_dict={x:batch_xs,y_:batch_ys,keep_prob:0.75})
if i%50 == 0:
train_accuracy = accuracy.eval(feed_dict={x:batch_xs, y_: batch_ys, keep_prob: 1.0})
print ("step {}, training accuracy {}".format(i, train_accuracy))
#计算准确率
print("train accuracy:",accuracy.eval({x:mnist_data.train.images,y_:mnist_data.train.labels,keep_prob:1.0}))
print("test accuracy:",accuracy.eval({x:mnist_data.test.images,y_:mnist_data.test.labels,keep_prob:1.0}))
Tensorboard可视化Tensorflow计算图,首先是将计算图中的节点和边直接可视化,其次是根据每个计算节点的命名空间来整理可视化得到效果图,使得神经网络的整体框架结构不会被过多的细节所淹没。可视化不仅显示Tensorflow计算图的结构,还可以展示计算节点上的信息进行描述统计,包括频数统计和分布统计。
为了有层次、抓住主体结构的可视化效果,Tensorboard通过命名空间来整理可视化效果图上的节点。在Tensorboard的默认视图中,计算图中同一个命名空间下的所有节点会被缩略为一个节点,而顶层命名空间的节点才会被显示在Tensorboard可视化效果图中。
命名空间采用树状结构,逐级细化节点和参数。我们以上面准备出来的简单神经网络为例,神经网络第一层命名为如下形式。
Tensorflow命名空间函数是tf.name_scope(),其作用为:
(1)在某个tf.name_scope()指定的区域中定义的所有对象及各种操作,他们的“name”属性上会增加该命名区的区域名,用以区别对象属于哪个区域;
(2)将不同的对象及操作放在由tf.name_scope()指定的区域中,便于在tensorboard中展示清晰的逻辑关系图,这点在复杂关系图中特别重要;
(3)只决定“对象”属于哪个范围和逻辑层次,并不会对“对象”的“作用域”产生任何影响;
(4)对于多重命名空间,也就是树状结构,需要多个with tf.name_scope()重叠使用。
with tf.name_scope("Layer1"):
with tf.name_scope('Weights'):
w1 = tf.Variable(tf.truncated_normal([in_units,h1_units],stddev=0.1),name='weights1')
tf.summary.histogram('weights',w1)
with tf.name_scope('biases'):
b1 = tf.Variable(tf.zeros([h1_units],dtype=tf.float32),name='biases1')
tf.summary.histogram('biases',b1)
#定义前向传播过程
h1 = tf.nn.relu(tf.add(tf.matmul(x,w1),b1))
#使用dropout
h1_drop = tf.nn.dropout(h1,keep_prob)
tf.summary.histogram('outputs', h1_drop)
在训练神经网络时,我们可通过tf.summary.histogram()查看一个张量在训练过程中值的分布情况,其分布情况是以直方图的形式在TensorBoard直方图仪表板上显示。
例如:
b1 = tf.Variable(tf.zeros([h1_units],dtype=tf.float32),name='biases1')
tf.summary.histogram('biases',b1)
展现图像时,distributions显示内容解析是distributions图和histogram图显示的数据源是相同的,只是用不同的方式对相同的内容进行展示。
在tensorflow变量初始化之前,使用tf.summary.merge_all()函数合并所定义采集点变量汇总,并且使用tf.summary.FileWriter函数将它们写到之前定义的采集日志路径。
在训练神经网络过程中,把参数记录到指定文件中,例如本文中的文件夹“mlp_logs”。
summ = tf.summary.merge_all()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
writer = tf.summary.FileWriter("mlp_logs/", graph=tf.get_default_graph())
日志书写器FileWriter中“mlp_logs”是日志文件所在的目录,这里是工程目录下的目录,第二个参数是事件文件要记录的图,也就是TensorFlow默认的图。
通过训练过程中sess.run()函数,同时运行汇总节点(本案例中的summ)。
......
writer = tf.summary.FileWriter("mlp_logs/", graph=tf.get_default_graph())
for i in range(3000):
batch_xs,batch_ys = mnist_data.train.next_batch(100)
_,loss_,summary = sess.run([train_step, loss_func, summ],feed_dict={x:batch_xs,y_:batch_ys,keep_prob:0.75})
if i%50 == 0:
train_accuracy = accuracy.eval(feed_dict={x:batch_xs, y_: batch_ys, keep_prob: 1.0})
writer.add_summary(summary, i) #将日志写入文件
print ("step {}, training accuracy {}".format(i, train_accuracy))
总结上述过程如下:
最后,完整的多层神经网络示例代码如下:
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
#获取所有的数据集
mnist_data = input_data.read_data_sets("/MNIST_data",one_hot=True)
#定义神经网络的参数
in_units = 784
h1_units = 300
#定义输入变量
x = tf.placeholder(dtype=tf.float32,shape=[None,in_units],name='x')
#定义输出变量
y_ = tf.placeholder(dtype=tf.float32,shape=[None,10],name='y_')
#定义dropout保留的节点数量
keep_prob = tf.placeholder(dtype=tf.float32,name='keep_prob')
with tf.name_scope("Layer1"):
with tf.name_scope('Weights'):
w1 = tf.Variable(tf.truncated_normal([in_units,h1_units],stddev=0.1),name='weights1')
tf.summary.histogram('weights',w1)
with tf.name_scope('biases'):
b1 = tf.Variable(tf.zeros([h1_units],dtype=tf.float32),name='biases1')
tf.summary.histogram('biases',b1)
#定义前向传播过程
h1 = tf.nn.relu(tf.add(tf.matmul(x,w1),b1))
#使用dropout
h1_drop = tf.nn.dropout(h1,keep_prob)
tf.summary.histogram('outputs', h1_drop)
#手写数字0到9,10个
with tf.name_scope("Layer2"):
with tf.name_scope('Weights'):
w2 = tf.Variable(tf.truncated_normal([h1_units,10],stddev=0.1),dtype=tf.float32,name='weights2')
tf.summary.histogram('weights',w2)
with tf.name_scope('biases'):
b2 = tf.Variable(tf.zeros([10],dtype=tf.float32),name='biases2')
tf.summary.histogram('biases',b2)
#定义输出y
y_conv = tf.nn.softmax(tf.matmul(h1_drop,w2)+b2,name='y')
tf.summary.histogram('outputs', y_conv)
#定义损失函数
with tf.name_scope("loss"):
loss_func = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1]))
tf.summary.scalar("loss",loss_func)
with tf.name_scope('Optimizer'):
train_step = tf.train.AdagradOptimizer(0.3).minimize(loss_func)
with tf.name_scope('accuracy'):
correct_pred = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
tf.summary.scalar('accuracy', accuracy)
tf.summary.histogram('accuracy', accuracy)
summ = tf.summary.merge_all()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
writer = tf.summary.FileWriter("mlp_logs/", graph=tf.get_default_graph())
for i in range(3000):
batch_xs,batch_ys = mnist_data.train.next_batch(100)
_,loss_,summary = sess.run([train_step, loss_func, summ],feed_dict={x:batch_xs,y_:batch_ys,keep_prob:0.75})
#writer.add_summary(summary, i) #将日志写入文件
if i%50 == 0:
train_accuracy = accuracy.eval(feed_dict={x:batch_xs, y_: batch_ys, keep_prob: 1.0})
writer.add_summary(summary, i) #将日志写入文件
print ("step {}, training accuracy {}".format(i, train_accuracy))
#计算准确率
print("train accuracy:",accuracy.eval({x:mnist_data.train.images,y_:mnist_data.train.labels,keep_prob:1.0}))
print("test accuracy:",accuracy.eval({x:mnist_data.test.images,y_:mnist_data.test.labels,keep_prob:1.0}))
接下来,我们使用TensorBoard进行可视化分析,在命令行窗口输入 tensorboard –logdir=mlp_log。在浏览器中打开“http://DESKTOP-KLSHRU3:6006”
D:\06Study\PyDev\Study\src>tensorboard --logdir mlp_logs
TensorBoard 1.10.0 at http://DESKTOP-KLSHRU3:6006 (Press CTRL+C to quit)
如果想终止TensorBoard的服务,可在开启这个服务的终端窗口,同时按下组合键“CTRL+C”,来终止它。
参考:
《tensorflow学习5:使用tensorboard可视化loss,weight,biases》 CSDN博客 xiexu911 2019.03
《使用Python开发工具Jupyter Notebook学习Tensorflow入门及Tensorboard实践》 CSDN博客 肖永威 2019.01