在TensorFlow中,最常用的可视化方法有三种途径,分别为TensorFlow与OpenCv的混合编程、利用Matpltlib进行可视化、利用TensorFlow自带的可视化工具TensorBoard进行可视化。这三种方法中,TensorFlow中最重要的可视化方法是通过tensorBoard、tf.summary和tf.summary.FileWriter这三个模块相互合作来完成的。
1、TensorBoard简介
TensorBoard是TensorFlow官方推出的可视化工具,它可以将模型训练过程中的各种汇总数据展示出来,包括标量(Scalar)、图片(Images)、音频(Audio)、计算图(Graphs)、数据分布(Distributions)、直方图(Histograms)和嵌入向量(Embeddings)。在训练大型深度学习神经网络时,中间计算过程非常复杂,为了理解调试和优化我们设计的网络,我们可以使用TensorBoard观察训练过程中各种可视化数据。如果要使用TensorBoard展示数据,我们需要在执行TensorFlow计算图的过程中,将各种类型的数据汇总并记录到日志文件中。然后使用TensorBoard读取这些日志文件,解析数据并生成可视化的Web界面,让我们可以在浏览器中观察各种汇总的数据。
2、Summary方法详解:
(2)tf.summary.histogram():用来显示直方图信息,其格式为:tf.summary.scalar(name, tensor, collections=None)
例如:tf.summary.scalar('mean', mean)
一般在画loss,accuary时会用到这个函数。
tf.summary.histogram(tags, values, collections=None, name=None)
例如: tf.summary.histogram('histogram', var)
一般用来显示训练过程中变量的分布情况
(3)tf.summary.distribution():分布图,一般用于显示weights分布
(4)tf.summary.text ():可以将文本类型的数据转换为tensor写入summary中:例如:
text = """/a/b/c\\_d/f\\_g\\_h\\_2017"""
summary_op0 = tf.summary.text('text', tf.convert_to_tensor(text))
格式:tf.summary.image(name, tensor, max_outputs=3, collections=None)
(6)tf.summary.audio():展示训练过程中记录的音频
(7)tf.summary.merge_all():merge_all 可以将所有summary全部保存到磁盘,以便tensorboard显示。
(8)tf.summary.FileWriter():指定一个文件用来保存图。如果没有特殊要求,一般用这一句就可一显示训练时的各种信息了。
格式:tf.summaries.merge_all(key='summaries')
Tensorflow Summary 用法示例:格式:tf.summary.FileWritter(path,sess.graph)
可以调用其add_summary()方法将训练过程数据保存在filewriter指定的文件中
(9)tf.summary.merge():有选择性地保存信息tf.summary.scalar('accuracy',acc) #生成准确率标量图
merge_summary = tf.summary.merge_all()
train_writer = tf.summary.FileWriter(dir,sess.graph)#定义一个写入summary的目标文件,dir为写入文件地址
......(交叉熵、优化器等定义)
for step in xrange(training_step): #训练循环
train_summary = sess.run(merge_summary,feed_dict = {...})#调用sess.run运行图,生成一步的训练过程数据
train_writer.add_summary(train_summary,step)#调用train_writer的add_summary方法将训练过程以及训练步数保存
此时到日志的目录下启动CMD,开启tensorborad:tensorboard –logdir=./
便能看见accuracy曲线了。另外,如果我不想保存所有定义的summary信息,也可以用tf.summary.merge方法有选择性地保存信息
示例:格式:tf.summary.merge(inputs, collections=None, name=None)
一般选择要保存的信息还需要用到tf.get_collection()函数
tf.summary.scalar('accuracy',acc) #生成准确率标量图
merge_summary = tf.summary.merge([tf.get_collection(tf.GraphKeys.SUMMARIES,'accuracy'),...(其他要显示的信息)])
train_writer = tf.summary.FileWriter(dir,sess.graph)#定义一个写入summary的目标文件,dir为写入文件地址
......(交叉熵、优化器等定义)
for step in xrange(training_step): #训练循环
train_summary = sess.run(merge_summary,feed_dict = {...})#调用sess.run运行图,生成一步的训练过程数据
train_writer.add_summary(train_summary,step)#调用train_writer的add_summary方法将训练过程以及训练步数保存
使用tf.get_collection函数筛选图中summary信息中的accuracy信息,这里的
tf.GraphKeys.SUMMARIES 是summary在collection中的标志。
当然,也可以直接:
acc_summary = tf.summary.scalar('accuracy',acc) #生成准确率标量图
merge_summary = tf.summary.merge([acc_summary ,...(其他要显示的信息)]) #这里的[]不可省
3、实例:用MLP训练mnist数据集
#coding=utf-8 import tensorflow as tf import pickle import numpy as np max_steps=1000 # 最大迭代次数 learning_rate=0.001 # 学习率 dropout=0.9 # dropout概率 log_dir="E:/testdata/mnist_log" # 保存训练日志的目录,给TensorBoard使用 # 定义一个mnist数据集的类 class mnistReader(): def __init__(self,mnistPath,onehot=True): self.mnistPath=mnistPath self.onehot=onehot self.batch_index=0 print ('read:',self.mnistPath) fo = open(self.mnistPath, 'rb') self.train_set,self.valid_set,self.test_set = pickle.load(fo,encoding='bytes') fo.close() self.data_label_train=list(zip(self.train_set[0],self.train_set[1])) np.random.shuffle(self.data_label_train) # 获取下一个训练集的batch def next_train_batch(self,batch_size=100): if self.batch_index < len(self.data_label_train)/batch_size: print ("batch_index:",self.batch_index ) datum=self.data_label_train[self.batch_index*batch_size:(self.batch_index+1)*batch_size] self.batch_index+=1 return self._decode(datum,self.onehot) else: self.batch_index=0 np.random.shuffle(self.data_label_train) datum=self.data_label_train[self.batch_index*batch_size:(self.batch_index+1)*batch_size] self.batch_index+=1 return self._decode(datum,self.onehot) # 获取测试集的数据 def test_data(self): tdata,tlabel=self.test_set data_label_test=list(zip(tdata,tlabel)) return self._decode(data_label_test,self.onehot) # 把一个batch的训练数据转换为可以放入模型训练的数据 def _decode(self,datum,onehot): rdata=list() # batch训练数据 rlabel=list() if onehot: for d,l in datum: rdata.append(np.reshape(d,[784])) # 转变形状为:一维向量 hot=np.zeros(10) hot[int(l)]=1 # label设为100维的one-hot向量 rlabel.append(hot) else: for d,l in datum: rdata.append(np.reshape(d,[784])) rlabel.append(int(l)) return rdata,rlabel sess=tf.InteractiveSession() # 定义占位符,x是训练数据,y_是label 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') # 对输入图像转换形状为一通道 with tf.name_scope('input_reshape'): image_reshaped_input=tf.reshape(x,[-1,28,28,1]) tf.summary.image('input',image_reshaped_input,10) # 图片汇总给TensorBoard,写入10张图片 # 权重初始化函数 def weight_variable(shape): 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) # 变量的数据汇总函数:均值、方差、最大值、最小值、直方图 def variable_summaries(var): 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('histogram',var) # 定义多层感知机,对权重、偏置、激活前、激活后数据进行汇总 def nn_layer(input_tensor,input_dim,output_dim,layer_name,act=tf.nn.relu): with tf.name_scope(layer_name): with tf.name_scope('weights'): weights=weight_variable([input_dim,output_dim]) variable_summaries(weights) with tf.name_scope('biases'): biases=bias_variable([output_dim]) variable_summaries(biases) with tf.name_scope('Wx_plus_b'): preactivate=tf.matmul(input_tensor,weights)+biases tf.summary.histogram('pre_activations',preactivate) activations=act(preactivate,name='activation') tf.summary.histogram('activations',activations) return activations # 定义第一个隐藏层 hidden1=nn_layer(x,784,500,'layer1') # 定义Dropout层并汇总Dropout with tf.name_scope('dropout'): keep_prob=tf.placeholder(tf.float32) tf.summary.scalar('dropout_keep_probability',keep_prob) dropped=tf.nn.dropout(hidden1,keep_prob) # 定义全连接层 y=nn_layer(dropped,500,10,'layer2',act=tf.identity) # 定义交叉熵并汇总 with tf.name_scope('cross_entropy'): diff=tf.nn.softmax_cross_entropy_with_logits(logits=y,labels=y_) with tf.name_scope('total'): cross_entropy=tf.reduce_mean(diff) tf.summary.scalar('cross_entropy',cross_entropy) # 定义优化器 with tf.name_scope('train'): train_step=tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy) # 定义准确率并汇总 with tf.name_scope('accuracy'): with tf.name_scope('correct_prediction'): correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) with tf.name_scope('accuracy'): accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) tf.summary.scalar('accuracy',accuracy) # 把所有的汇总信息进行合并 merged=tf.summary.merge_all() # 定义训练和测试的日志文件写入器 train_writer=tf.summary.FileWriter(log_dir+'/train',sess.graph) test_writer=tf.summary.FileWriter(log_dir+'/test') mnist=mnistReader(mnistPath="E:/testdata/mnist.pkl") tf.global_variables_initializer().run() # 定义填充真数据字典的函数 def feed_dict(train): if train: xs,ys=mnist.next_train_batch() k=dropout else: xs,ys=mnist.test_data() k=1.0 return {x:xs,y_:ys,keep_prob:k} # 保存训练结果的saver saver=tf.train.Saver() # 开始训练 for i in range(max_steps): # 每10次计算一次准确率 if i%10==0: summary,acc=sess.run([merged,accuracy],feed_dict=feed_dict(False)) test_writer.add_summary(summary,i) print ('accuracy at step %s:%s'%(i,acc)) else: # 每100次保存一次训练结果 if i%100==99: run_options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE) run_metadata=tf.RunMetadata() summary,_=sess.run([merged,train_step],feed_dict=feed_dict(True),options=run_options,run_metadata=run_metadata) train_writer.add_summary(summary,i) saver.save(sess,log_dir+'/model.ckpt',i) print ('adding run metedata for ',i) else: summary,_=sess.run([merged,train_step],feed_dict=feed_dict(True)) train_writer.add_summary(summary,i) train_writer.close() test_writer.close()
接下来启动TensorBoard,在E:/testdata/mnist_log目录下启动命令行CMD:tensorboard –logdir=./
然后在浏览器输入地址:http://Lenovo-495:6006
参考:https://blog.csdn.net/hongxue8888/article/details/79753679
https://www.tensorflow.org/programmers_guide/summaries_and_tensorboard