aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <gardener@tensorflow.org>2017-05-30 19:01:39 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2017-05-30 19:05:23 -0700
commit37d9d5f0e877064899f10ab7fed0934d08049662 (patch)
treec700ced38f81b430ef3c7d9d30c3259a62a2dfb4
parentd58cd296202b89440f59c2bcc8776a6eb08dc961 (diff)
Add some routines for managing summaries to slim.
PiperOrigin-RevId: 157541902
-rw-r--r--tensorflow/contrib/slim/BUILD27
-rw-r--r--tensorflow/contrib/slim/__init__.py1
-rw-r--r--tensorflow/contrib/slim/python/slim/summaries.py220
-rw-r--r--tensorflow/contrib/slim/python/slim/summaries_test.py108
4 files changed, 356 insertions, 0 deletions
diff --git a/tensorflow/contrib/slim/BUILD b/tensorflow/contrib/slim/BUILD
index 012413d8e9..fbe8ced46e 100644
--- a/tensorflow/contrib/slim/BUILD
+++ b/tensorflow/contrib/slim/BUILD
@@ -144,6 +144,7 @@ py_library(
":learning",
":model_analyzer",
":queues",
+ ":summaries",
"//tensorflow/contrib/framework:framework_py",
"//tensorflow/contrib/layers:layers_py",
"//tensorflow/contrib/losses:losses_py",
@@ -160,6 +161,32 @@ py_library(
],
)
+py_library(
+ name = "summaries",
+ srcs = ["python/slim/summaries.py"],
+ srcs_version = "PY2AND3",
+ deps = [
+ "//tensorflow/python:framework",
+ "//tensorflow/python:logging_ops",
+ "//tensorflow/python:nn",
+ "//tensorflow/python:summary",
+ ],
+)
+
+py_test(
+ name = "summaries_test",
+ srcs = ["python/slim/summaries_test.py"],
+ srcs_version = "PY2AND3",
+ deps = [
+ ":summaries",
+ "//tensorflow/python:array_ops",
+ "//tensorflow/python:client_testlib",
+ "//tensorflow/python:framework",
+ "//tensorflow/python:platform",
+ "//tensorflow/python:summary",
+ ],
+)
+
filegroup(
name = "all_files",
srcs = glob(
diff --git a/tensorflow/contrib/slim/__init__.py b/tensorflow/contrib/slim/__init__.py
index 67846a95fd..22998b1126 100644
--- a/tensorflow/contrib/slim/__init__.py
+++ b/tensorflow/contrib/slim/__init__.py
@@ -34,6 +34,7 @@ from tensorflow.contrib.slim.python.slim import evaluation
from tensorflow.contrib.slim.python.slim import learning
from tensorflow.contrib.slim.python.slim import model_analyzer
from tensorflow.contrib.slim.python.slim import queues
+from tensorflow.contrib.slim.python.slim import summaries
from tensorflow.contrib.slim.python.slim.data import data_decoder
from tensorflow.contrib.slim.python.slim.data import data_provider
from tensorflow.contrib.slim.python.slim.data import dataset
diff --git a/tensorflow/contrib/slim/python/slim/summaries.py b/tensorflow/contrib/slim/python/slim/summaries.py
new file mode 100644
index 0000000000..358359d6eb
--- /dev/null
+++ b/tensorflow/contrib/slim/python/slim/summaries.py
@@ -0,0 +1,220 @@
+# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ==============================================================================
+"""Contains helper functions for creating summaries.
+
+This module contains various helper functions for quickly and easily adding
+tensorflow summaries. These allow users to print summary values
+automatically as they are computed and add prefixes to collections of summaries.
+
+Example usage:
+
+ import tensorflow as tf
+ slim = tf.contrib.slim
+
+ slim.summaries.add_histogram_summaries(slim.variables.get_model_variables())
+ slim.summaries.add_scalar_summary(total_loss, 'Total Loss')
+ slim.summaries.add_scalar_summary(learning_rate, 'Learning Rate')
+ slim.summaries.add_histogram_summaries(my_tensors)
+ slim.summaries.add_zero_fraction_summaries(my_tensors)
+"""
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+from tensorflow.python.framework import ops
+from tensorflow.python.ops import logging_ops
+from tensorflow.python.ops import nn_impl as nn
+from tensorflow.python.summary import summary
+
+
+def _get_summary_name(tensor, name=None, prefix=None, postfix=None):
+ """Produces the summary name given.
+
+ Args:
+ tensor: A variable or op `Tensor`.
+ name: The optional name for the summary.
+ prefix: An optional prefix for the summary name.
+ postfix: An optional postfix for the summary name.
+
+ Returns:
+ a summary name.
+ """
+ if not name:
+ name = tensor.op.name
+ if prefix:
+ name = prefix + '/' + name
+ if postfix:
+ name = name + '/' + postfix
+ return name
+
+
+def add_histogram_summary(tensor, name=None, prefix=None):
+ """Adds a histogram summary for the given tensor.
+
+ Args:
+ tensor: A variable or op tensor.
+ name: The optional name for the summary.
+ prefix: An optional prefix for the summary names.
+
+ Returns:
+ A scalar `Tensor` of type `string` whose contents are the serialized
+ `Summary` protocol buffer.
+ """
+ return summary.histogram(
+ _get_summary_name(tensor, name, prefix), tensor)
+
+
+def add_image_summary(tensor, name=None, prefix=None, print_summary=False):
+ """Adds an image summary for the given tensor.
+
+ Args:
+ tensor: a variable or op tensor with shape [batch,height,width,channels]
+ name: the optional name for the summary.
+ prefix: An optional prefix for the summary names.
+ print_summary: If `True`, the summary is printed to stdout when the summary
+ is computed.
+
+ Returns:
+ An image `Tensor` of type `string` whose contents are the serialized
+ `Summary` protocol buffer.
+ """
+ summary_name = _get_summary_name(tensor, name, prefix)
+ # If print_summary, then we need to make sure that this call doesn't add the
+ # non-printing op to the collection. We'll add it to the collection later.
+ collections = [] if print_summary else None
+ op = summary.image(
+ name=summary_name, tensor=tensor, collections=collections)
+ if print_summary:
+ op = logging_ops.Print(op, [tensor], summary_name)
+ ops.add_to_collection(ops.GraphKeys.SUMMARIES, op)
+ return op
+
+
+def add_scalar_summary(tensor, name=None, prefix=None, print_summary=False):
+ """Adds a scalar summary for the given tensor.
+
+ Args:
+ tensor: a variable or op tensor.
+ name: the optional name for the summary.
+ prefix: An optional prefix for the summary names.
+ print_summary: If `True`, the summary is printed to stdout when the summary
+ is computed.
+
+ Returns:
+ A scalar `Tensor` of type `string` whose contents are the serialized
+ `Summary` protocol buffer.
+ """
+ collections = [] if print_summary else None
+ summary_name = _get_summary_name(tensor, name, prefix)
+
+ # If print_summary, then we need to make sure that this call doesn't add the
+ # non-printing op to the collection. We'll add it to the collection later.
+ op = summary.scalar(
+ name=summary_name, tensor=tensor, collections=collections)
+ if print_summary:
+ op = logging_ops.Print(op, [tensor], summary_name)
+ ops.add_to_collection(ops.GraphKeys.SUMMARIES, op)
+ return op
+
+
+def add_zero_fraction_summary(tensor, name=None, prefix=None,
+ print_summary=False):
+ """Adds a summary for the percentage of zero values in the given tensor.
+
+ Args:
+ tensor: a variable or op tensor.
+ name: the optional name for the summary.
+ prefix: An optional prefix for the summary names.
+ print_summary: If `True`, the summary is printed to stdout when the summary
+ is computed.
+
+ Returns:
+ A scalar `Tensor` of type `string` whose contents are the serialized
+ `Summary` protocol buffer.
+ """
+ name = _get_summary_name(tensor, name, prefix, 'Fraction of Zero Values')
+ tensor = nn.zero_fraction(tensor)
+ return add_scalar_summary(tensor, name, print_summary=print_summary)
+
+
+def add_histogram_summaries(tensors, prefix=None):
+ """Adds a histogram summary for each of the given tensors.
+
+ Args:
+ tensors: A list of variable or op tensors.
+ prefix: An optional prefix for the summary names.
+
+ Returns:
+ A list of scalar `Tensors` of type `string` whose contents are the
+ serialized `Summary` protocol buffer.
+ """
+ summary_ops = []
+ for tensor in tensors:
+ summary_ops.append(add_histogram_summary(tensor, prefix=prefix))
+ return summary_ops
+
+
+def add_image_summaries(tensors, prefix=None):
+ """Adds an image summary for each of the given tensors.
+
+ Args:
+ tensors: A list of variable or op tensors.
+ prefix: An optional prefix for the summary names.
+
+ Returns:
+ A list of scalar `Tensors` of type `string` whose contents are the
+ serialized `Summary` protocol buffer.
+ """
+ summary_ops = []
+ for tensor in tensors:
+ summary_ops.append(add_image_summary(tensor, prefix=prefix))
+ return summary_ops
+
+
+def add_scalar_summaries(tensors, prefix=None, print_summary=False):
+ """Adds a scalar summary for each of the given tensors.
+
+ Args:
+ tensors: a list of variable or op tensors.
+ prefix: An optional prefix for the summary names.
+ print_summary: If `True`, the summary is printed to stdout when the summary
+ is computed.
+
+ Returns:
+ A list of scalar `Tensors` of type `string` whose contents are the
+ serialized `Summary` protocol buffer.
+ """
+ summary_ops = []
+ for tensor in tensors:
+ summary_ops.append(add_scalar_summary(tensor, prefix=prefix,
+ print_summary=print_summary))
+ return summary_ops
+
+
+def add_zero_fraction_summaries(tensors, prefix=None):
+ """Adds a scalar zero-fraction summary for each of the given tensors.
+
+ Args:
+ tensors: a list of variable or op tensors.
+ prefix: An optional prefix for the summary names.
+
+ Returns:
+ A list of scalar `Tensors` of type `string` whose contents are the
+ serialized `Summary` protocol buffer.
+ """
+ summary_ops = []
+ for tensor in tensors:
+ summary_ops.append(add_zero_fraction_summary(tensor, prefix=prefix))
+ return summary_ops
diff --git a/tensorflow/contrib/slim/python/slim/summaries_test.py b/tensorflow/contrib/slim/python/slim/summaries_test.py
new file mode 100644
index 0000000000..873ee78de2
--- /dev/null
+++ b/tensorflow/contrib/slim/python/slim/summaries_test.py
@@ -0,0 +1,108 @@
+# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ==============================================================================
+"""Tests for tensorflow.contrib.slim.summaries."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import glob
+import os
+
+
+from tensorflow.contrib.slim.python.slim import summaries
+from tensorflow.python.framework import ops
+from tensorflow.python.ops import array_ops
+from tensorflow.python.platform import gfile
+from tensorflow.python.platform import test
+from tensorflow.python.summary import summary
+from tensorflow.python.summary import summary_iterator
+
+
+class SummariesTest(test.TestCase):
+
+ def safe_create(self, output_dir):
+ if gfile.Exists(output_dir):
+ gfile.DeleteRecursively(output_dir)
+ gfile.MakeDirs(output_dir)
+
+ def assert_scalar_summary(self, output_dir, names_to_values):
+ """Asserts that the given output directory contains written summaries.
+
+ Args:
+ output_dir: The output directory in which to look for even tfiles.
+ names_to_values: A dictionary of summary names to values.
+ """
+ # The events file may have additional entries, e.g. the event version
+ # stamp, so have to parse things a bit.
+ output_filepath = glob.glob(os.path.join(output_dir, '*'))
+ self.assertEqual(len(output_filepath), 1)
+
+ events = summary_iterator.summary_iterator(output_filepath[0])
+ summaries_list = [e.summary for e in events if e.summary.value]
+ values = []
+ for item in summaries_list:
+ for value in item.value:
+ values.append(value)
+ saved_results = {v.tag: v.simple_value for v in values}
+ for name in names_to_values:
+ self.assertAlmostEqual(names_to_values[name], saved_results[name])
+
+ def testScalarSummaryIsPartOfCollectionWithNoPrint(self):
+ tensor = array_ops.ones([]) * 3
+ name = 'my_score'
+ prefix = 'eval'
+ op = summaries.add_scalar_summary(tensor, name, prefix, print_summary=False)
+ self.assertTrue(op in ops.get_collection(ops.GraphKeys.SUMMARIES))
+
+ def testScalarSummaryIsPartOfCollectionWithPrint(self):
+ tensor = array_ops.ones([]) * 3
+ name = 'my_score'
+ prefix = 'eval'
+ op = summaries.add_scalar_summary(tensor, name, prefix, print_summary=True)
+ self.assertTrue(op in ops.get_collection(ops.GraphKeys.SUMMARIES))
+
+ def verify_scalar_summary_is_written(self, print_summary):
+ value = 3
+ tensor = array_ops.ones([]) * value
+ name = 'my_score'
+ prefix = 'eval'
+ summaries.add_scalar_summary(tensor, name, prefix, print_summary)
+
+ output_dir = os.path.join(self.get_temp_dir(),
+ 'scalar_summary_no_print_test')
+ self.safe_create(output_dir)
+
+ summary_op = summary.merge_all()
+
+ summary_writer = summary.FileWriter(output_dir)
+ with self.test_session() as sess:
+ new_summary = sess.run(summary_op)
+ summary_writer.add_summary(new_summary, 1)
+ summary_writer.flush()
+
+ self.assert_scalar_summary(output_dir, {
+ '%s/%s' % (prefix, name): value
+ })
+
+ def testScalarSummaryIsWrittenWithNoPrint(self):
+ self.verify_scalar_summary_is_written(print_summary=False)
+
+ def testScalarSummaryIsWrittenWithPrint(self):
+ self.verify_scalar_summary_is_written(print_summary=True)
+
+
+if __name__ == '__main__':
+ test.main()