aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/python/training/summary_io.py
diff options
context:
space:
mode:
Diffstat (limited to 'tensorflow/python/training/summary_io.py')
-rw-r--r--tensorflow/python/training/summary_io.py226
1 files changed, 226 insertions, 0 deletions
diff --git a/tensorflow/python/training/summary_io.py b/tensorflow/python/training/summary_io.py
new file mode 100644
index 0000000000..dd994c5311
--- /dev/null
+++ b/tensorflow/python/training/summary_io.py
@@ -0,0 +1,226 @@
+"""Reads Summaries from and writes Summaries to event files."""
+
+import os.path
+import Queue
+import threading
+import time
+
+from tensorflow.core.framework import summary_pb2
+from tensorflow.core.util import event_pb2
+from tensorflow.python import pywrap_tensorflow
+from tensorflow.python.lib.io import tf_record
+from tensorflow.python.platform import gfile
+
+
+class SummaryWriter(object):
+ """Writes `Summary` protocol buffers to event files.
+
+ The `SummaryWriter` class provides a mechanism to create an event file in a
+ given directory and add summaries and events to it. The class updates the
+ file contents asynchronously. This allows a training program to call methods
+ to add data to the file directly from the training loop, without slowing down
+ training.
+
+ @@__init__
+
+ @@add_summary
+ @@add_event
+ @@add_graph
+
+ @@flush
+ @@close
+ """
+
+ def __init__(self, logdir, graph_def=None, max_queue=10, flush_secs=120):
+ """Creates a `SummaryWriter` and an event file.
+
+ On construction the summary writer creates a new event file in `logdir`.
+ This event file will contain `Event` protocol buffers constructed when you
+ call one of the following functions: `add_summary()`, `add_event()`, or
+ `add_graph()`.
+
+ If you pass a `graph_def` protocol buffer to the constructor it is added to
+ the event file. (This is equivalent to calling `add_graph()` later).
+
+ TensorBoard will pick the graph from the file and display it graphically so
+ you can interactively explore the graph you built. You will usually pass
+ the graph from the session in which you launched it:
+
+ ```python
+ ...create a graph...
+ # Launch the graph in a session.
+ sess = tf.Session()
+ # Create a summary writer, add the 'graph_def' to the event file.
+ writer = tf.train.SummaryWriter(<some-directory>, sess.graph_def)
+ ```
+
+ The other arguments to the constructor control the asynchronous writes to
+ the event file:
+
+ * `flush_secs`: How often, in seconds, to flush the added summaries
+ and events to disk.
+ * `max_queue`: Maximum number of summaries or events pending to be
+ written to disk before one of the 'add' calls block.
+
+ Args:
+ logdir: A string. Directory where event file will be written.
+ graph_def: A `GraphDef` protocol buffer.
+ max_queue: Integer. Size of the queue for pending events and summaries.
+ flush_secs: Number. How often, in seconds, to flush the
+ pending events and summaries to disk.
+ """
+ self._logdir = logdir
+ if not gfile.IsDirectory(self._logdir):
+ gfile.MakeDirs(self._logdir)
+ self._event_queue = Queue.Queue(max_queue)
+ self._ev_writer = pywrap_tensorflow.EventsWriter(
+ os.path.join(self._logdir, "events"))
+ self._worker = _EventLoggerThread(self._event_queue, self._ev_writer,
+ flush_secs)
+ self._worker.start()
+ if graph_def is not None:
+ self.add_graph(graph_def)
+
+ def add_summary(self, summary, global_step=None):
+ """Adds a `Summary` protocol buffer to the event file.
+
+ This method wraps the provided summary in an `Event` procotol buffer
+ and adds it to the event file.
+
+ You can pass the output of any summary op, as-is, to this function. You
+ can also pass a `Summary` procotol buffer that you manufacture with your
+ own data. This is commonly done to report evaluation results in event
+ files.
+
+ Args:
+ summary: A `Summary` protocol buffer, optionally serialized as a string.
+ global_step: Number. Optional global step value to record with the
+ summary.
+ """
+ if isinstance(summary, basestring):
+ summ = summary_pb2.Summary()
+ summ.ParseFromString(summary)
+ summary = summ
+ event = event_pb2.Event(wall_time=time.time(), summary=summary)
+ if global_step is not None:
+ event.step = long(global_step)
+ self.add_event(event)
+
+ def add_event(self, event):
+ """Adds an event to the event file.
+
+ Args:
+ event: An `Event` protocol buffer.
+ """
+ self._event_queue.put(event)
+
+ def add_graph(self, graph_def, global_step=None):
+ """Adds a `GraphDef` protocol buffer to the event file.
+
+ The graph described by the protocol buffer will be displayed by
+ TensorBoard. Most users pass a graph in the constructor instead.
+
+ Args:
+ graph_def: A `GraphDef` protocol buffer.
+ global_step: Number. Optional global step counter to record with the
+ graph.
+ """
+ event = event_pb2.Event(wall_time=time.time(), graph_def=graph_def)
+ if global_step is not None:
+ event.step = long(global_step)
+ self._event_queue.put(event)
+
+ def flush(self):
+ """Flushes the event file to disk.
+
+ Call this method to make sure that all pending events have been written to
+ disk.
+ """
+ self._event_queue.join()
+ self._ev_writer.Flush()
+
+ def close(self):
+ """Flushes the event file to disk and close the file.
+
+ Call this method when you do not need the summary writer anymore.
+ """
+ self.flush()
+ self._ev_writer.Close()
+
+
+class _EventLoggerThread(threading.Thread):
+ """Thread that logs events."""
+
+ def __init__(self, queue, ev_writer, flush_secs):
+ """Creates an _EventLoggerThread.
+
+ Args:
+ queue: a Queue from which to dequeue events.
+ ev_writer: an event writer. Used to log brain events for
+ the visualizer.
+ flush_secs: How often, in seconds, to flush the
+ pending file to disk.
+ """
+ threading.Thread.__init__(self)
+ self.daemon = True
+ self._queue = queue
+ self._ev_writer = ev_writer
+ self._flush_secs = flush_secs
+ # The first event will be flushed immediately.
+ self._next_event_flush_time = 0
+
+ def run(self):
+ while True:
+ event = self._queue.get()
+ try:
+ self._ev_writer.WriteEvent(event)
+ # Flush the event writer every so often.
+ now = time.time()
+ if now > self._next_event_flush_time:
+ self._ev_writer.Flush()
+ # Do it again in two minutes.
+ self._next_event_flush_time = now + self._flush_secs
+ finally:
+ self._queue.task_done()
+
+
+def summary_iterator(path):
+ """An iterator for reading `Event` protocol buffers from an event file.
+
+ You can use this function to read events written to an event file. It returns
+ a Python iterator that yields `Event` protocol buffers.
+
+ Example: Print the contents of an events file.
+
+ ```python
+ for e in tf.summary_iterator(path to events file):
+ print e
+ ```
+
+ Example: Print selected summary values.
+
+ ```python
+ # This example supposes that the events file contains summaries with a
+ # summary value tag 'loss'. These could have been added by calling
+ # `add_summary()`, passing the output of a scalar summary op created with
+ # with: `tf.scalar_summary(['loss'], loss_tensor)`.
+ for e in tf.summary_iterator(path to events file):
+ for v in e.summary.value:
+ if v.tag == 'loss':
+ print v.simple_value
+ ```
+
+ See the protocol buffer definitions of
+ [Event](https://tensorflow.googlesource.com/tensorflow/+/master/tensorflow/core/util/event.proto)
+ and
+ [Summary](https://tensorflow.googlesource.com/tensorflow/+/master/tensorflow/core/framework/summary.proto)
+ for more information about their attributes.
+
+ Args:
+ path: The path to an event file created by a `SummaryWriter`.
+
+ Yields:
+ `Event` protocol buffers.
+ """
+ for r in tf_record.tf_record_iterator(path):
+ yield event_pb2.Event.FromString(r)