基于TensorBoard中graph模块图结构分析


Posted in Python onFebruary 15, 2020

在上一篇文章中,我们介绍了如何使用源码对TensorBoard进行编译教程,没有定制需求的可以直接使用pip进行安装。

TensorBoard中的graph是一种计算图,里面的点用于表示Tensor本身或者运算符,图中的边则代表Tensor的流动或者控制关系。

基于TensorBoard中graph模块图结构分析

本文主要从代码的层面,分析graph的数据来源与结构。

一般来说,我们在启动TensorBoard的时候会使用--logdir参数配置文件路径(或者设置数据库位置),这些日志文件为TensorBoard提供了数据。于是我们打开一个日志文件,查看里面的内容

基于TensorBoard中graph模块图结构分析

我们看到,文件是通过二进制展示的,因此无法直接读取文件的内容。

回到浏览器中,进入graph页面,通过开发者工具发现,构造图的时候调用了一个接口

http://localhost:6006/data/plugin/graphs/graph?large_attrs_key=_too_large_attrs&limit_attr_size=1024&run=task1

用浏览器打开这个地址,看到以下内容

node {
 name: "Input/X"
 op: "Placeholder"
 attr {
 key: "_output_shapes"
 value {
  list {
  shape {
   unknown_rank: true
  }
  }
 }
 }
 attr {
 key: "dtype"
 value {
  type: DT_FLOAT
 }
 }
 attr {
 key: "shape"
 value {
  shape {
  unknown_rank: true
  }
 }
 }
}
...

每个node都能够与图中的一个节点相对应,因此我们可以确定,这个接口里返回的node,就是构成图所需要的数据结构。

那么,TensorBoard是如何将日志文件转化为图的呢?

TesnorBoard中的每个模块都是以plugin存在的,我们进入tensorboard/plugin/graph/graphs_plungin.py,在这个文件中定义了graph相关的接口

def get_plugin_apps(self):
 return {
  '/graph': self.graph_route,
  '/runs': self.runs_route,
  '/run_metadata': self.run_metadata_route,
  '/run_metadata_tags': self.run_metadata_tags_route,
 }

我们可以看到,‘/graph'这个接口返回值为self.graph_route,在这个文件中搜索graph_route方法

@wrappers.Request.application
 def graph_route(self, request):
 """Given a single run, return the graph definition in protobuf format."""
 run = request.args.get('run')
 if run is None:
  return http_util.Respond(
   request, 'query parameter "run" is required', 'text/plain', 400)
 
 limit_attr_size = request.args.get('limit_attr_size', None)
 if limit_attr_size is not None:
  try:
  limit_attr_size = int(limit_attr_size)
  except ValueError:
  return http_util.Respond(
   request, 'query parameter `limit_attr_size` must be an integer',
   'text/plain', 400)
 
 large_attrs_key = request.args.get('large_attrs_key', None)
 
 try:
  result = self.graph_impl(run, limit_attr_size, large_attrs_key)
 except ValueError as e:
  return http_util.Respond(request, e.message, 'text/plain', code=400)
 else:
  if result is not None:
  (body, mime_type) = result # pylint: disable=unpacking-non-sequence
  return http_util.Respond(request, body, mime_type)
  else:
  return http_util.Respond(request, '404 Not Found', 'text/plain',
         code=404)

在这个方法中,分别取了“run”,”limit_attr_size“和“large_attrs_key”三个参数,和前面url所调用的参数一致,说明这个是我们要找的方法。在方法的最后,调用了self.graph_impl生成了图,我们继续查看这个方法

def graph_impl(self, run, limit_attr_size=None, large_attrs_key=None):
 """Result of the form `(body, mime_type)`, or `None` if no graph exists."""
 try:
  graph = self._multiplexer.Graph(run)
 except ValueError:
  return None
 # This next line might raise a ValueError if the limit parameters
 # are invalid (size is negative, size present but key absent, etc.).
 process_graph.prepare_graph_for_ui(graph, limit_attr_size, large_attrs_key)
 return (str(graph), 'text/x-protobuf') # pbtxt

这个方法调用了self._multiplexer.Graph(run)生成图。_multiplexer是一个event_multiplexer实例,在graph_plugln初始化时通过base_plaugin.TBContext获得。

def __init__(self, context):
 """Instantiates GraphsPlugin via TensorBoard core.
 Args:
  context: A base_plugin.TBContext instance.
 """
 self._multiplexer = context.multiplexer

进入tensorboard/backend/event_processing/event_multiplexer,找到Graph方法

def Graph(self, run):
 """Retrieve the graph associated with the provided run.
 Args:
  run: A string name of a run to load the graph for.
 Raises:
  KeyError: If the run is not found.
  ValueError: If the run does not have an associated graph.
 Returns:
  The `GraphDef` protobuf data structure.
 """
 accumulator = self.GetAccumulator(run)
 return accumulator.Graph()
 
 def GetAccumulator(self, run):
 """Returns EventAccumulator for a given run.
 Args:
  run: String name of run.
 Returns:
  An EventAccumulator object.
 Raises:
  KeyError: If run does not exist.
 """
 with self._accumulators_mutex:
  return self._accumulators[run]

Graph方法获取了run对应的accumulator实例,并返回了这个实例的Graph方法的返回值。我们进入tensorboard/backend/event_processing/event_accumulator,找到Graph()方法

def Graph(self):
 """Return the graph definition, if there is one.
 If the graph is stored directly, return that. If no graph is stored
 directly but a metagraph is stored containing a graph, return that.
 Raises:
  ValueError: If there is no graph for this run.
 Returns:
  The `graph_def` proto.
 """
 graph = tf.GraphDef()
 if self._graph is not None:
  graph.ParseFromString(self._graph)
  return graph
 raise ValueError('There is no graph in this EventAccumulator')

事实上,它返回了一个GraphDef图,因此我们也可以通过将日志转换为GraphDef的方式读取日志。

# 导入要用到的基本模块。为了在python2、python3 中可以使用E侣兼容的 print 函数
from __future__ import print_function
import numpy as np
import tensorflow as tf
 
# 创建图和Session
graph = tf.Graph()
sess = tf.InteractiveSession(graph=graph)
 
#日志路径
model_fn = '/log/events.out.tfevents.1535957014.ubuntu'
 
for e in tf.train.summary_iterator(model_fn):
 if e.HasField('graph_def'):
  graph = e.graph_def;
  graph_def = tf.GraphDef()
  graph_def.ParseFromString(graph)
  print(graph_def)

我们新建一个python文件,修改日志路径为自己的日志位置,便可以得到与TensorBoard相同的内容。

以上这篇基于TensorBoard中graph模块图结构分析就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
常见的在Python中实现单例模式的三种方法
Apr 08 Python
两个使用Python脚本操作文件的小示例分享
Aug 27 Python
Python编程中装饰器的使用示例解析
Jun 20 Python
使用Python实现毫秒级抢单功能
Jun 06 Python
Python实现时间序列可视化的方法
Aug 06 Python
Pandas DataFrame中的tuple元素遍历的实现
Oct 23 Python
使用apiDoc实现python接口文档编写
Nov 19 Python
python 3.8.3 安装配置图文教程
May 21 Python
python3 简单实现组合设计模式
Jul 02 Python
python爬虫 requests-html的使用
Nov 30 Python
matplotlib绘制鼠标的十字光标的实现(自定义方式,官方实例)
Jan 10 Python
python 实现Requests发送带cookies的请求
Feb 08 Python
使用Bazel编译TensorBoard教程
Feb 15 #Python
TensorBoard 计算图的可视化实现
Feb 15 #Python
TensorBoard 计算图的查看方式
Feb 15 #Python
pycharm 更改创建文件默认路径的操作
Feb 15 #Python
PyCharm刷新项目(文件)目录的实现
Feb 14 #Python
浅谈Pycharm最有必要改的几个默认设置项
Feb 14 #Python
python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法
Feb 14 #Python
You might like
vs中通过剪切板循环来循环粘贴不同内容
2011/04/30 PHP
php 转换字符串编码 iconv与mb_convert_encoding的区别说明
2011/11/10 PHP
PHP时间戳与日期之间转换的实例介绍
2013/04/19 PHP
php使用Cookie控制访问授权的方法
2015/01/21 PHP
如何正确配置Nginx + PHP
2016/07/15 PHP
Laravel如何实现自动加载类
2019/10/14 PHP
js 多种变量定义(对象直接量,数组直接量和函数直接量)
2010/05/24 Javascript
9行javascript代码获取QQ群成员具体实现
2013/10/16 Javascript
js实现幻灯片播放图片示例代码
2013/11/07 Javascript
jqGrid日期格式的判断示例代码(开始日期与结束日期)
2013/11/08 Javascript
15位和18位身份证JS校验的简单实例
2016/07/18 Javascript
在 Node.js 中使用 async 函数的方法
2017/11/17 Javascript
Vue2.0结合webuploader实现文件分片上传功能
2018/03/09 Javascript
layer提示框添加多个按钮选择的实例
2019/09/12 Javascript
深入理解基于vue-cli的webpack打包优化实践及探索
2019/10/14 Javascript
JavaScript交换变量的常用方法小结【4种方法】
2020/05/07 Javascript
js实现炫酷光感效果
2020/09/05 Javascript
[01:19:34]2014 DOTA2国际邀请赛中国区预选赛 New Element VS Dream time
2014/05/22 DOTA
python中xrange用法分析
2015/04/15 Python
Python基于百度AI实现OCR文字识别
2020/04/02 Python
关于matplotlib-legend 位置属性 loc 使用说明
2020/05/16 Python
Python如何测试stdout输出
2020/08/10 Python
windows下python 3.9 Numpy scipy和matlabplot的安装教程详解
2020/11/28 Python
CSS3实现红包抖动效果
2020/12/23 HTML / CSS
美国领先的家庭智能音响系统品牌:Sonos
2018/07/20 全球购物
一站式跨境收款解决方案:Payoneer(派安盈)
2018/09/06 全球购物
Chain Reaction Cycles俄罗斯:世界上最大的在线自行车商店
2019/08/27 全球购物
Hotels.com拉丁美洲:从豪华酒店到经济型酒店的预定优惠和折扣
2019/12/09 全球购物
内容编辑个人求职信
2013/12/10 职场文书
文艺委员竞选稿
2015/11/19 职场文书
HTML+CSS+JS实现图片的瀑布流布局的示例代码
2021/04/22 HTML / CSS
python文件目录操作之os模块
2021/05/08 Python
Mysql数据库值的添加、修改、删除及清空操作实例
2021/06/20 MySQL
Redis Cluster 集群搭建你会吗
2021/08/04 Redis
CSS作用域(样式分割)的使用汇总
2021/11/07 HTML / CSS
Oracle表空间与权限的深入讲解
2021/11/17 Oracle