基于TensorBoard中g(shù)raph模塊圖結(jié)構(gòu)分析
在上一篇文章中,我們介紹了如何使用源碼對(duì)TensorBoard進(jìn)行編譯教程,沒(méi)有定制需求的可以直接使用pip進(jìn)行安裝。
TensorBoard中的graph是一種計(jì)算圖,里面的點(diǎn)用于表示Tensor本身或者運(yùn)算符,圖中的邊則代表Tensor的流動(dòng)或者控制關(guān)系。
本文主要從代碼的層面,分析graph的數(shù)據(jù)來(lái)源與結(jié)構(gòu)。
一般來(lái)說(shuō),我們?cè)趩?dòng)TensorBoard的時(shí)候會(huì)使用--logdir參數(shù)配置文件路徑(或者設(shè)置數(shù)據(jù)庫(kù)位置),這些日志文件為T(mén)ensorBoard提供了數(shù)據(jù)。于是我們打開(kāi)一個(gè)日志文件,查看里面的內(nèi)容
我們看到,文件是通過(guò)二進(jìn)制展示的,因此無(wú)法直接讀取文件的內(nèi)容。
回到瀏覽器中,進(jìn)入graph頁(yè)面,通過(guò)開(kāi)發(fā)者工具發(fā)現(xiàn),構(gòu)造圖的時(shí)候調(diào)用了一個(gè)接口
http://localhost:6006/data/plugin/graphs/graph?large_attrs_key=_too_large_attrs&limit_attr_size=1024&run=task1
用瀏覽器打開(kāi)這個(gè)地址,看到以下內(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 } } } } ...
每個(gè)node都能夠與圖中的一個(gè)節(jié)點(diǎn)相對(duì)應(yīng),因此我們可以確定,這個(gè)接口里返回的node,就是構(gòu)成圖所需要的數(shù)據(jù)結(jié)構(gòu)。
那么,TensorBoard是如何將日志文件轉(zhuǎn)化為圖的呢?
TesnorBoard中的每個(gè)模塊都是以plugin存在的,我們進(jìn)入tensorboard/plugin/graph/graphs_plungin.py,在這個(gè)文件中定義了graph相關(guān)的接口
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'這個(gè)接口返回值為self.graph_route,在這個(gè)文件中搜索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)
在這個(gè)方法中,分別取了“run”,”limit_attr_size“和“l(fā)arge_attrs_key”三個(gè)參數(shù),和前面url所調(diào)用的參數(shù)一致,說(shuō)明這個(gè)是我們要找的方法。在方法的最后,調(diào)用了self.graph_impl生成了圖,我們繼續(xù)查看這個(gè)方法
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
這個(gè)方法調(diào)用了self._multiplexer.Graph(run)生成圖。_multiplexer是一個(gè)event_multiplexer實(shí)例,在graph_plugln初始化時(shí)通過(guò)base_plaugin.TBContext獲得。
def __init__(self, context): """Instantiates GraphsPlugin via TensorBoard core. Args: context: A base_plugin.TBContext instance. """ self._multiplexer = context.multiplexer
進(jìn)入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對(duì)應(yīng)的accumulator實(shí)例,并返回了這個(gè)實(shí)例的Graph方法的返回值。我們進(jìn)入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')
事實(shí)上,它返回了一個(gè)GraphDef圖,因此我們也可以通過(guò)將日志轉(zhuǎn)換為GraphDef的方式讀取日志。
# 導(dǎo)入要用到的基本模塊。為了在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)
我們新建一個(gè)python文件,修改日志路徑為自己的日志位置,便可以得到與TensorBoard相同的內(nèi)容。
以上這篇基于TensorBoard中g(shù)raph模塊圖結(jié)構(gòu)分析就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python中函數(shù)的參數(shù)傳遞與可變長(zhǎng)參數(shù)介紹
這篇文章主要介紹了Python中函數(shù)的參數(shù)傳遞與可變長(zhǎng)參數(shù)介紹,本文分別給出多個(gè)代碼實(shí)例來(lái)講解多種多樣的函數(shù)參數(shù),需要的朋友可以參考下2015-06-06Pycharm自帶Git實(shí)現(xiàn)版本管理的方法步驟
這篇文章主要介紹了Pycharm自帶Git實(shí)現(xiàn)版本管理的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09詳解Python使用simplejson模塊解析JSON的方法
這篇文章主要介紹了Python使用simplejson模塊解析JSON的方法,實(shí)例代碼基于Pyhton2.x版本,文中最后還附了關(guān)于simplejson模塊的一些性能放面的討論,需要的朋友可以參考下2016-03-03python使用標(biāo)準(zhǔn)庫(kù)根據(jù)進(jìn)程名如何獲取進(jìn)程的pid詳解
Python有一套很有用的標(biāo)準(zhǔn)庫(kù)(standard library)。標(biāo)準(zhǔn)庫(kù)會(huì)隨著Python解釋器,一起安裝在你的電腦中的,所以下面這篇文章主要給大家介紹了關(guān)于python使用標(biāo)準(zhǔn)庫(kù)根據(jù)進(jìn)程名如何獲取進(jìn)程pid的相關(guān)資料,需要的朋友可以參考下。2017-10-10Python實(shí)現(xiàn)自定義順序、排列寫(xiě)入數(shù)據(jù)到Excel的方法
這篇文章主要介紹了Python實(shí)現(xiàn)自定義順序、排列寫(xiě)入數(shù)據(jù)到Excel的方法,涉及Python針對(duì)Excel文件的數(shù)據(jù)處理及讀寫(xiě)相關(guān)操作技巧,需要的朋友可以參考下2018-04-04python+selenium實(shí)現(xiàn)登錄賬戶后自動(dòng)點(diǎn)擊的示例
本篇文章主要介紹了python+selenium實(shí)現(xiàn)登錄賬戶后自動(dòng)點(diǎn)擊的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12關(guān)于Python列表元素排序操作sort()、min()、max()函數(shù)用法
這篇文章主要介紹了關(guān)于Python列表元素排序操作sort()、min()、max()函數(shù)用法,python中提供了列表元素的操作函數(shù),那么這些函數(shù)該怎么使用呢,感興趣的朋友一起來(lái)看看吧2023-04-04