From f41959ccb2d9d4c722fe8fc3351401d53bcf4900 Mon Sep 17 00:00:00 2001 From: Manjunath Kudlur Date: Fri, 6 Nov 2015 16:27:58 -0800 Subject: TensorFlow: Initial commit of TensorFlow library. TensorFlow is an open source software library for numerical computation using data flow graphs. Base CL: 107276108 --- tensorflow/tensorboard/tensorboard.py | 139 ++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 tensorflow/tensorboard/tensorboard.py (limited to 'tensorflow/tensorboard/tensorboard.py') diff --git a/tensorflow/tensorboard/tensorboard.py b/tensorflow/tensorboard/tensorboard.py new file mode 100644 index 0000000000..dcbc50401c --- /dev/null +++ b/tensorflow/tensorboard/tensorboard.py @@ -0,0 +1,139 @@ +"""Serve TensorFlow summary data to a web frontend. + +This is a simple web server to proxy data from the event_loader to the web, and +serve static web files. +""" + +import BaseHTTPServer +import functools +import os +import socket +import SocketServer + +import tensorflow.python.platform + +from tensorflow.python.platform import app +from tensorflow.python.platform import flags +from tensorflow.python.platform import logging +from tensorflow.python.platform import status_bar +from tensorflow.python.summary import event_accumulator +from tensorflow.python.summary import event_multiplexer +from tensorflow.tensorboard import tensorboard_handler + +flags.DEFINE_string('logdir', None, """ +logdir specifies where TensorBoard will look to find TensorFlow event files +that it can display. In the simplest case, logdir is a directory containing +tfevents files. TensorBoard also supports comparing multiple TensorFlow +executions: to do this, you can use directory whose subdirectories contain +tfevents files, as in the following example: + +foo/bar/logdir/ +foo/bar/logdir/mnist_1/events.out.tfevents.1444088766 +foo/bar/logdir/mnist_2/events.out.tfevents.1444090064 + +You may also pass a comma seperated list of log directories, and you can +assign names to individual log directories by putting a colon between the name +and the path, as in + +tensorboard --logdir=name1:/path/to/logs/1,name2:/path/to/logs/2 +""") +flags.DEFINE_boolean('debug', False, 'Whether to run the app in debug mode. ' + 'This increases log verbosity to DEBUG.') +flags.DEFINE_string('host', '0.0.0.0', 'What host to listen to. Defaults to ' + 'allowing remote access, set to 127.0.0.1 to serve only on ' + 'localhost.') +flags.DEFINE_integer('port', 6006, 'What port to serve TensorBoard on.') + +FLAGS = flags.FLAGS + +# How many elements to store per tag, by tag type +TENSORBOARD_SIZE_GUIDANCE = { + event_accumulator.COMPRESSED_HISTOGRAMS: 500, + event_accumulator.IMAGES: 4, + event_accumulator.SCALARS: 10000, + event_accumulator.HISTOGRAMS: 1, +} + + +def ParseEventFilesFlag(flag_value): + """Parses the logdir flag into a map from paths to run group names. + + The events files flag format is a comma-separated list of path specifications. + A path specification either looks like 'group_name:/path/to/directory' or + '/path/to/directory'; in the latter case, the group is unnamed. Group names + cannot start with a forward slash: /foo:bar/baz will be interpreted as a + spec with no name and path '/foo:bar/baz'. + + Globs are not supported. + + Args: + flag_value: A comma-separated list of run specifications. + Returns: + A dict mapping directory paths to names like {'/path/to/directory': 'name'}. + Groups without an explicit name are named after their path. If flag_value + is None, returns an empty dict, which is helpful for testing things that + don't require any valid runs. + """ + files = {} + if flag_value is None: + return files + for specification in flag_value.split(','): + # If the spec looks like /foo:bar/baz, then we assume it's a path with a + # colon. + if ':' in specification and specification[0] != '/': + # We split at most once so run_name:/path:with/a/colon will work. + run_name, path = specification.split(':', 1) + else: + run_name = None + path = specification + files[path] = run_name + return files + + +class ThreadedHTTPServer(SocketServer.ThreadingMixIn, + BaseHTTPServer.HTTPServer): + """A threaded HTTP server.""" + daemon = True + + +def main(unused_argv=None): + # Change current working directory to tensorflow/'s parent directory. + server_root = os.path.join(os.path.dirname(__file__), + os.pardir, os.pardir) + os.chdir(server_root) + + if FLAGS.debug: + logging.set_verbosity(logging.DEBUG) + + if not FLAGS.logdir: + logging.error('A logdir must be specified. Run `tensorboard --help` for ' + 'details and examples.') + return -1 + + if FLAGS.debug: + logging.info('Starting TensorBoard in directory %s' % os.getcwd()) + + path_to_run = ParseEventFilesFlag(FLAGS.logdir) + multiplexer = event_multiplexer.AutoloadingMultiplexer( + path_to_run=path_to_run, interval_secs=60, + size_guidance=TENSORBOARD_SIZE_GUIDANCE) + + multiplexer.AutoUpdate(interval=30) + + factory = functools.partial(tensorboard_handler.TensorboardHandler, + multiplexer) + try: + server = ThreadedHTTPServer((FLAGS.host, FLAGS.port), factory) + except socket.error: + logging.error('Tried to connect to port %d, but that address is in use.' % + FLAGS.port) + return -2 + + status_bar.SetupStatusBarInsideGoogle('TensorBoard', FLAGS.port) + print 'Starting TensorBoard on port %d' % FLAGS.port + print '(You can navigate to http://localhost:%d)' % FLAGS.port + server.serve_forever() + + +if __name__ == '__main__': + app.run() -- cgit v1.2.3