1# Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15 16"""Tensor summaries for exporting information about a model. 17 18See the @{$python/summary} guide. 19 20@@FileWriter 21@@FileWriterCache 22@@tensor_summary 23@@scalar 24@@histogram 25@@audio 26@@image 27@@text 28@@merge 29@@merge_all 30@@get_summary_description 31@@PluginAsset 32@@get_plugin_asset 33@@get_all_plugin_assets 34""" 35 36from __future__ import absolute_import 37from __future__ import division 38from __future__ import print_function 39 40from google.protobuf import json_format as _json_format 41 42# exports Summary, SummaryDescription, Event, TaggedRunMetadata, SessionLog 43# pylint: disable=unused-import 44from tensorflow.core.framework.summary_pb2 import Summary 45from tensorflow.core.framework.summary_pb2 import SummaryDescription 46from tensorflow.core.util.event_pb2 import Event 47from tensorflow.core.util.event_pb2 import SessionLog 48from tensorflow.core.util.event_pb2 import TaggedRunMetadata 49# pylint: enable=unused-import 50 51from tensorflow.python.eager import context as _context 52from tensorflow.python.framework import dtypes as _dtypes 53from tensorflow.python.framework import ops as _ops 54from tensorflow.python.ops import gen_logging_ops as _gen_logging_ops 55from tensorflow.python.ops import summary_op_util as _summary_op_util 56 57# exports tensor-related summaries 58# pylint: disable=unused-import 59from tensorflow.python.ops.summary_ops import tensor_summary 60# pylint: enable=unused-import 61 62# exports text 63# pylint: disable=unused-import 64from tensorflow.python.summary.text_summary import text_summary as text 65# pylint: enable=unused-import 66 67# exports FileWriter, FileWriterCache 68# pylint: disable=unused-import 69from tensorflow.python.summary.writer.writer import FileWriter 70from tensorflow.python.summary.writer.writer_cache import FileWriterCache 71# pylint: enable=unused-import 72 73from tensorflow.python.util import compat as _compat 74from tensorflow.python.util.all_util import remove_undocumented 75from tensorflow.python.util.tf_export import tf_export 76 77 78@tf_export('summary.scalar') 79def scalar(name, tensor, collections=None, family=None): 80 """Outputs a `Summary` protocol buffer containing a single scalar value. 81 82 The generated Summary has a Tensor.proto containing the input Tensor. 83 84 Args: 85 name: A name for the generated node. Will also serve as the series name in 86 TensorBoard. 87 tensor: A real numeric Tensor containing a single value. 88 collections: Optional list of graph collections keys. The new summary op is 89 added to these collections. Defaults to `[GraphKeys.SUMMARIES]`. 90 family: Optional; if provided, used as the prefix of the summary tag name, 91 which controls the tab name used for display on Tensorboard. 92 93 Returns: 94 A scalar `Tensor` of type `string`. Which contains a `Summary` protobuf. 95 96 Raises: 97 ValueError: If tensor has the wrong shape or type. 98 """ 99 with _summary_op_util.summary_scope( 100 name, family, values=[tensor]) as (tag, scope): 101 # pylint: disable=protected-access 102 val = _gen_logging_ops._scalar_summary(tags=tag, values=tensor, name=scope) 103 _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES]) 104 return val 105 106 107@tf_export('summary.image') 108def image(name, tensor, max_outputs=3, collections=None, family=None): 109 """Outputs a `Summary` protocol buffer with images. 110 111 The summary has up to `max_outputs` summary values containing images. The 112 images are built from `tensor` which must be 4-D with shape `[batch_size, 113 height, width, channels]` and where `channels` can be: 114 115 * 1: `tensor` is interpreted as Grayscale. 116 * 3: `tensor` is interpreted as RGB. 117 * 4: `tensor` is interpreted as RGBA. 118 119 The images have the same number of channels as the input tensor. For float 120 input, the values are normalized one image at a time to fit in the range 121 `[0, 255]`. `uint8` values are unchanged. The op uses two different 122 normalization algorithms: 123 124 * If the input values are all positive, they are rescaled so the largest one 125 is 255. 126 127 * If any input value is negative, the values are shifted so input value 0.0 128 is at 127. They are then rescaled so that either the smallest value is 0, 129 or the largest one is 255. 130 131 The `tag` in the outputted Summary.Value protobufs is generated based on the 132 name, with a suffix depending on the max_outputs setting: 133 134 * If `max_outputs` is 1, the summary value tag is '*name*/image'. 135 * If `max_outputs` is greater than 1, the summary value tags are 136 generated sequentially as '*name*/image/0', '*name*/image/1', etc. 137 138 Args: 139 name: A name for the generated node. Will also serve as a series name in 140 TensorBoard. 141 tensor: A 4-D `uint8` or `float32` `Tensor` of shape `[batch_size, height, 142 width, channels]` where `channels` is 1, 3, or 4. 143 max_outputs: Max number of batch elements to generate images for. 144 collections: Optional list of ops.GraphKeys. The collections to add the 145 summary to. Defaults to [_ops.GraphKeys.SUMMARIES] 146 family: Optional; if provided, used as the prefix of the summary tag name, 147 which controls the tab name used for display on Tensorboard. 148 149 Returns: 150 A scalar `Tensor` of type `string`. The serialized `Summary` protocol 151 buffer. 152 """ 153 with _summary_op_util.summary_scope( 154 name, family, values=[tensor]) as (tag, scope): 155 # pylint: disable=protected-access 156 val = _gen_logging_ops._image_summary( 157 tag=tag, tensor=tensor, max_images=max_outputs, name=scope) 158 _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES]) 159 return val 160 161 162@tf_export('summary.histogram') 163def histogram(name, values, collections=None, family=None): 164 # pylint: disable=line-too-long 165 """Outputs a `Summary` protocol buffer with a histogram. 166 167 Adding a histogram summary makes it possible to visualize your data's 168 distribution in TensorBoard. You can see a detailed explanation of the 169 TensorBoard histogram dashboard 170 [here](https://www.tensorflow.org/get_started/tensorboard_histograms). 171 172 The generated 173 [`Summary`](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto) 174 has one summary value containing a histogram for `values`. 175 176 This op reports an `InvalidArgument` error if any value is not finite. 177 178 Args: 179 name: A name for the generated node. Will also serve as a series name in 180 TensorBoard. 181 values: A real numeric `Tensor`. Any shape. Values to use to 182 build the histogram. 183 collections: Optional list of graph collections keys. The new summary op is 184 added to these collections. Defaults to `[GraphKeys.SUMMARIES]`. 185 family: Optional; if provided, used as the prefix of the summary tag name, 186 which controls the tab name used for display on Tensorboard. 187 188 Returns: 189 A scalar `Tensor` of type `string`. The serialized `Summary` protocol 190 buffer. 191 """ 192 with _summary_op_util.summary_scope( 193 name, family, values=[values], 194 default_name='HistogramSummary') as (tag, scope): 195 # pylint: disable=protected-access 196 val = _gen_logging_ops._histogram_summary( 197 tag=tag, values=values, name=scope) 198 _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES]) 199 return val 200 201 202@tf_export('summary.audio') 203def audio(name, tensor, sample_rate, max_outputs=3, collections=None, 204 family=None): 205 # pylint: disable=line-too-long 206 """Outputs a `Summary` protocol buffer with audio. 207 208 The summary has up to `max_outputs` summary values containing audio. The 209 audio is built from `tensor` which must be 3-D with shape `[batch_size, 210 frames, channels]` or 2-D with shape `[batch_size, frames]`. The values are 211 assumed to be in the range of `[-1.0, 1.0]` with a sample rate of 212 `sample_rate`. 213 214 The `tag` in the outputted Summary.Value protobufs is generated based on the 215 name, with a suffix depending on the max_outputs setting: 216 217 * If `max_outputs` is 1, the summary value tag is '*name*/audio'. 218 * If `max_outputs` is greater than 1, the summary value tags are 219 generated sequentially as '*name*/audio/0', '*name*/audio/1', etc 220 221 Args: 222 name: A name for the generated node. Will also serve as a series name in 223 TensorBoard. 224 tensor: A 3-D `float32` `Tensor` of shape `[batch_size, frames, channels]` 225 or a 2-D `float32` `Tensor` of shape `[batch_size, frames]`. 226 sample_rate: A Scalar `float32` `Tensor` indicating the sample rate of the 227 signal in hertz. 228 max_outputs: Max number of batch elements to generate audio for. 229 collections: Optional list of ops.GraphKeys. The collections to add the 230 summary to. Defaults to [_ops.GraphKeys.SUMMARIES] 231 family: Optional; if provided, used as the prefix of the summary tag name, 232 which controls the tab name used for display on Tensorboard. 233 234 Returns: 235 A scalar `Tensor` of type `string`. The serialized `Summary` protocol 236 buffer. 237 """ 238 with _summary_op_util.summary_scope( 239 name, family=family, values=[tensor]) as (tag, scope): 240 # pylint: disable=protected-access 241 sample_rate = _ops.convert_to_tensor( 242 sample_rate, dtype=_dtypes.float32, name='sample_rate') 243 val = _gen_logging_ops._audio_summary_v2( 244 tag=tag, tensor=tensor, max_outputs=max_outputs, 245 sample_rate=sample_rate, name=scope) 246 _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES]) 247 return val 248 249 250@tf_export('summary.merge') 251def merge(inputs, collections=None, name=None): 252 # pylint: disable=line-too-long 253 """Merges summaries. 254 255 This op creates a 256 [`Summary`](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto) 257 protocol buffer that contains the union of all the values in the input 258 summaries. 259 260 When the Op is run, it reports an `InvalidArgument` error if multiple values 261 in the summaries to merge use the same tag. 262 263 Args: 264 inputs: A list of `string` `Tensor` objects containing serialized `Summary` 265 protocol buffers. 266 collections: Optional list of graph collections keys. The new summary op is 267 added to these collections. Defaults to `[]`. 268 name: A name for the operation (optional). 269 270 Returns: 271 A scalar `Tensor` of type `string`. The serialized `Summary` protocol 272 buffer resulting from the merging. 273 274 Raises: 275 RuntimeError: If called with eager mode enabled. 276 277 @compatibility(eager) 278 Not compatible with eager execution. To write TensorBoard 279 summaries under eager execution, use `tf.contrib.summary` instead. 280 @end_compatbility 281 """ 282 # pylint: enable=line-too-long 283 if _context.in_eager_mode(): 284 raise RuntimeError( 285 'Merging tf.summary.* ops is not compatible with eager execution. ' 286 'Use tf.contrib.summary instead.') 287 name = _summary_op_util.clean_tag(name) 288 with _ops.name_scope(name, 'Merge', inputs): 289 # pylint: disable=protected-access 290 val = _gen_logging_ops._merge_summary(inputs=inputs, name=name) 291 _summary_op_util.collect(val, collections, []) 292 return val 293 294 295@tf_export('summary.merge_all') 296def merge_all(key=_ops.GraphKeys.SUMMARIES, scope=None): 297 """Merges all summaries collected in the default graph. 298 299 Args: 300 key: `GraphKey` used to collect the summaries. Defaults to 301 `GraphKeys.SUMMARIES`. 302 scope: Optional scope used to filter the summary ops, using `re.match` 303 304 Returns: 305 If no summaries were collected, returns None. Otherwise returns a scalar 306 `Tensor` of type `string` containing the serialized `Summary` protocol 307 buffer resulting from the merging. 308 309 Raises: 310 RuntimeError: If called with eager execution enabled. 311 312 @compatibility(eager) 313 Not compatible with eager execution. To write TensorBoard 314 summaries under eager execution, use `tf.contrib.summary` instead. 315 @end_compatbility 316 """ 317 if _context.in_eager_mode(): 318 raise RuntimeError( 319 'Merging tf.summary.* ops is not compatible with eager execution. ' 320 'Use tf.contrib.summary instead.') 321 summary_ops = _ops.get_collection(key, scope=scope) 322 if not summary_ops: 323 return None 324 else: 325 return merge(summary_ops) 326 327 328@tf_export('summary.get_summary_description') 329def get_summary_description(node_def): 330 """Given a TensorSummary node_def, retrieve its SummaryDescription. 331 332 When a Summary op is instantiated, a SummaryDescription of associated 333 metadata is stored in its NodeDef. This method retrieves the description. 334 335 Args: 336 node_def: the node_def_pb2.NodeDef of a TensorSummary op 337 338 Returns: 339 a summary_pb2.SummaryDescription 340 341 Raises: 342 ValueError: if the node is not a summary op. 343 344 @compatibility(eager) 345 Not compatible with eager execution. To write TensorBoard 346 summaries under eager execution, use `tf.contrib.summary` instead. 347 @end_compatbility 348 """ 349 350 if node_def.op != 'TensorSummary': 351 raise ValueError("Can't get_summary_description on %s" % node_def.op) 352 description_str = _compat.as_str_any(node_def.attr['description'].s) 353 summary_description = SummaryDescription() 354 _json_format.Parse(description_str, summary_description) 355 return summary_description 356 357 358_allowed_symbols = [ 359 'Summary', 'SummaryDescription', 'Event', 'TaggedRunMetadata', 'SessionLog', 360] 361 362remove_undocumented(__name__, _allowed_symbols) 363