基于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 27 Python
利用Hyperic调用Python实现进程守护
Jan 02 Python
5款非常棒的Python工具
Jan 05 Python
Python中顺序表的实现简单代码分享
Jan 09 Python
Python3使用正则表达式爬取内涵段子示例
Apr 22 Python
Python3用tkinter和PIL实现看图工具
Jun 21 Python
python基础学习之如何对元组各个元素进行命名详解
Jul 12 Python
Python抽象和自定义类定义与用法示例
Aug 23 Python
Python从ZabbixAPI获取信息及实现Zabbix-API 监控的方法
Sep 17 Python
Python进阶之@property动态属性的实现
Apr 01 Python
pyinstaller打包单个exe后无法执行错误的解决方法
Jun 21 Python
详解pandas数据合并与重塑(pd.concat篇)
Jul 09 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
PHP 基本语法格式
2009/12/15 PHP
PHP关于IE下的iframe跨域导致session丢失问题解决方法
2013/10/10 PHP
PHP定时更新程序设计思路分享
2014/06/10 PHP
分享一个php 的异常处理程序
2014/06/22 PHP
PHP Session机制简介及用法
2014/08/19 PHP
PHP7.1方括号数组符号多值复制及指定键值赋值用法分析
2016/09/26 PHP
php操作路径的经典方法(必看篇)
2016/10/04 PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
2016/10/10 PHP
jQuery选中select控件 无法设置selected的解决方法
2010/09/01 Javascript
JQuery 应用 JQuery.groupTable.js
2010/12/15 Javascript
JS解决ie6下png透明的方法实例
2013/08/02 Javascript
jquery中获取id值方法小结
2013/09/22 Javascript
jQuery异步上传文件插件ajaxFileUpload详细介绍
2015/05/19 Javascript
详解JavaScript的回调函数
2015/11/20 Javascript
JavaScript代码实现左右上下自动晃动自动移动
2016/04/08 Javascript
Vue框架里使用Swiper的方法示例
2018/09/20 Javascript
vue实现与安卓、IOS交互的方法
2018/11/02 Javascript
Layer.js实现表格溢出内容省略号显示,悬停显示全部的方法
2019/09/16 Javascript
[55:39]DOTA2-DPC中国联赛 正赛 VG vs LBZS BO3 第二场 1月19日
2021/03/11 DOTA
python导入模块交叉引用的方法
2019/01/19 Python
基于Python3.6中的OpenCV实现图片色彩空间的转换
2020/02/03 Python
PyCharm MySQL可视化Database配置过程图解
2020/06/09 Python
Pytorch 使用CNN图像分类的实现
2020/06/16 Python
CSS3的calc()做响应模式布局的实现方法
2017/09/06 HTML / CSS
英国网上香水店:Fragrance Direct
2016/07/20 全球购物
澳大利亚波希米亚风时尚品牌:Tree of Life
2019/09/15 全球购物
知识竞赛主持词
2014/03/26 职场文书
《天安门广场》教学反思
2014/04/23 职场文书
优秀安全员事迹材料
2014/05/11 职场文书
党员志愿者活动总结
2014/06/26 职场文书
员工激励培训演讲稿
2014/09/16 职场文书
2014年煤矿工人工作总结
2014/12/08 职场文书
云台山导游词
2015/02/03 职场文书
教师工作决心书
2015/02/04 职场文书
使用jpa之动态插入与修改(重写save)
2021/11/23 Java/Android
PostgreSQL13基于流复制搭建后备服务器的方法
2022/01/18 PostgreSQL