Tensorboard入门 | TensorFlow深度学习笔记
Tensorboard是TensorFlow自带的一个强大的可视化工具
01 功 能
这是TensorFlow在MNIST实验数据上得到Tensorboard结果(https://www.tensorflow.org/tensorboard/index.html#graphs)
- Event: 展示训练过程中的统计数据(最值,均值等)变化情况
- Image: 展示训练过程中记录的图像
- Audio: 展示训练过程中记录的音频
- Histogram: 展示训练过程中记录的数据的分布图
02
原 理
- 在运行过程中,记录结构化的数据
- 运行一个本地服务器,监听6006端口
- 请求时,分析记录的数据,绘制
03
实 现
在构建graph的过程中,记录你想要追踪的Tensor
with tf.name_scope('output_act'):
hidden = tf.nn.relu6(tf.matmul(reshape, output_weights[0]) + output_biases) tf.histogram_summary('output_act', hidden)
其中,
- histogram_summary用于生成分布图,也可以用scalar_summary记录存数值
- 使用scalar_summary的时候,tag和tensor的shape要一致
- name_scope可以不写,但是当你需要在Graph中体现tensor之间的包含关系时,就要写了,像下面这样:
with tf.name_scope('input_cnn_filter'):
with tf.name_scope('input_weight'):
input_weights = tf.Variable(tf.truncated_normal(
[patch_size, patch_size, num_channels, depth], stddev=0.1), name='input_weight') variable_summaries(input_weights, 'input_cnn_filter/input_weight')
with tf.name_scope('input_biases'):
input_biases = tf.Variable(tf.zeros([depth]), name='input_biases') variable_summaries(input_weights, 'input_cnn_filter/input_biases')
- 在Graph中会体现为一个input_cnn_filter,可以点开,里面有weight和biases
- 用summary系列函数记录后,Tensorboard会根据graph中的依赖关系在Graph标签中展示对应的图结构
- 官网封装了一个函数,可以调用来记录很多跟某个Tensor相关的数据:
def variable_summaries(var, name):
"""Attach a lot of summaries to a Tensor."""
with tf.name_scope('summaries'):
mean = tf.reduce_mean(var)
tf.scalar_summary('mean/' + name, mean)
with tf.name_scope('stddev'):
stddev = tf.sqrt(tf.reduce_sum(tf.square(var - mean))) tf.scalar_summary('sttdev/' + name, stddev)
tf.scalar_summary('max/' + name, tf.reduce_max(var))
tf.scalar_summary('min/' + name, tf.reduce_min(var))
tf.histogram_summary(name, var)
- 只有这样记录国max和min的Tensor才会出现在Event里面
- Graph的最后要写一句这个,给session回调
merged = tf.merge_all_summaries()
04
Session中调用
- 构造两个writer,分别在train和valid的时候写数据:
train_writer = tf.train.SummaryWriter(summary_dir + '/train', session.graph)valid_writer = tf.train.SummaryWriter(summary_dir + '/valid')
- 这里的summary_dir存放了运行过程中记录的数据,等下启动服务器要用到
- 构造run_option和run_meta,在每个step运行session时进行设置:
summary, _, l, predictions =
session.run([merged, optimizer, loss, train_prediction], options=run_options, feed_dict=feed_dict)
- 注意要把merged拿回来,并且设置options
- 在每次训练时,记一次:
train_writer.add_summary(summary, step)
- 在每次验证时,记一次:
valid_writer.add_summary(summary, step)
- 达到一定训练次数后,记一次meta做一下标记
train_writer.add_run_metadata(run_metadata, 'step%03d' % step)
05
查看可视化结果
- 启动TensorBoard服务器:
python安装路径/python TensorFlow安装路径/tensorflow/tensorboard/tensorboard.py --logdir=path/to/log-directory
注意这个python必须是安装了TensorFlow的python,tensorboard.py必须制定路径才能被python找到,logdir必须是前面创建两个writer时使用的路径
比如我的是:
/home/cwh/anaconda2/envs/tensorflow/bin/python /home/cwh/anaconda2/envs/tensorflow/lib/python2.7/site-packages/tensorflow/tensorboard/tensorboard.py --logdir=~/coding/python/GDLnotes/src/convnet/summary
使用python
- 然后在浏览器输入 http://127.0.0.1:6006 就可以访问到tensorboard的结果
06
强迫症踩坑后记
- 之前我的cnn代码里有valid_prediction,所以画出来的graph有两条分支,不太清晰,所以只留了train一个分支
修改前:
多分支graph
修改后:
单分支graph
- 多用with,进行包裹,这样才好看,正如官网说的,你的summary代码决定了你的图结构
- 不是所有的tensor都有必要记录,但是Variable和placeholder最好都用summary记录一下,也是为了好看
- 由于有了gradient的计算,所以与gradient计算相关的都会被拎出来,下次试一下用其他optimizer
我的CNN TensorBoard代码:cnn_board.py(https://github.com/ahangchen/GDLnotes/blob/master/src/convnet/cnn_board.py)
07
参考资料
- mnist_with_summaries.py (https://github.com/tensorflow/tensorflow/blob/r0.10/tensorflow/examples/tutorials/mnist/mnist_with_summaries.py)
Github地址:https://github.com/ahangchen/GDLnotes
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 都是微服务的天下了,还有不知道 JSON 的程序员吗?
- Codeforces Round #624 (Div. 3) D.Three Integers
- select 高级查询之连接查询
- select 高级查询之子查询
- Java 最实用的文件读写
- MySQL基本操作
- MySQL 索引
- notepad++ 配置c++及运行
- Leetcode 687. 最长同值路径
- Leetcode 1071. 字符串的最大公因子
- PAT (Advanced Level) Practice 1146 Topological Order (25分)
- 【风险预警】RPCBind服务被利用进行UDP反射DDoS攻击
- MySQL DDL 操作
- Leetcode 169 多数元素
- Codeforces Round #424 (Div. 1, rated, based on VK Cup Finals) B. Cards Sorting 树状数组+技巧