基于TensorBoard中graph模塊圖結構分析
在上一篇文章中,我們介紹了如何使用源碼對TensorBoard進行編譯教程,沒有定制需求的可以直接使用pip進行安裝。
TensorBoard中的graph是一種計算圖,里面的點用于表示Tensor本身或者運算符,圖中的邊則代表Tensor的流動或者控制關系。

本文主要從代碼的層面,分析graph的數(shù)據(jù)來源與結構。
一般來說,我們在啟動TensorBoard的時候會使用--logdir參數(shù)配置文件路徑(或者設置數(shù)據(jù)庫位置),這些日志文件為TensorBoard提供了數(shù)據(jù)。于是我們打開一個日志文件,查看里面的內(nèi)容

我們看到,文件是通過二進制展示的,因此無法直接讀取文件的內(nèi)容。
回到瀏覽器中,進入graph頁面,通過開發(fā)者工具發(fā)現(xiàn),構造圖的時候調(diào)用了一個接口
http://localhost:6006/data/plugin/graphs/graph?large_attrs_key=_too_large_attrs&limit_attr_size=1024&run=task1
用瀏覽器打開這個地址,看到以下內(nèi)容
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都能夠與圖中的一個節(jié)點相對應,因此我們可以確定,這個接口里返回的node,就是構成圖所需要的數(shù)據(jù)結構。
那么,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“和“l(fā)arge_attrs_key”三個參數(shù),和前面url所調(diào)用的參數(shù)一致,說明這個是我們要找的方法。在方法的最后,調(diào)用了self.graph_impl生成了圖,我們繼續(xù)查看這個方法
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
這個方法調(diào)用了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 函數(shù)
from __future__ import print_function
import numpy as np
import tensorflow as tf
# 創(chuàng)建圖和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相同的內(nèi)容。
以上這篇基于TensorBoard中graph模塊圖結構分析就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
解決TensorFlow訓練內(nèi)存不斷增長,進程被殺死問題
今天小編就為大家分享一篇解決TensorFlow訓練內(nèi)存不斷增長,進程被殺死問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
Python數(shù)據(jù)可視化編程通過Matplotlib創(chuàng)建散點圖代碼示例
這篇文章主要介紹了Python數(shù)據(jù)可視化編程通過Matplotlib創(chuàng)建散點圖實例,具有一定借鑒價值,需要的朋友可以參考下。2017-12-12
對Python中小整數(shù)對象池和大整數(shù)對象池的使用詳解
今天小編就為大家分享一篇對Python中小整數(shù)對象池和大整數(shù)對象池的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07
numpy中np.nanmax和np.max的區(qū)別及坑
這篇文章主要介紹了numpy中np.nanmax和np.max的區(qū)別及坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02

