Add some routines for managing summaries to slim.

PiperOrigin-RevId: 157541902
This commit is contained in:
A. Unique TensorFlower 2017-05-30 19:01:39 -07:00 committed by TensorFlower Gardener
parent d58cd29620
commit 37d9d5f0e8
4 changed files with 356 additions and 0 deletions

View File

@ -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(

View File

@ -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

View File

@ -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

View File

@ -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()