• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"""Operations for writing summary data, for use in analysis and visualization.
17
18See the [Summaries and
19TensorBoard](https://www.tensorflow.org/guide/summaries_and_tensorboard) guide.
20"""
21
22from __future__ import absolute_import
23from __future__ import division
24from __future__ import print_function
25
26from google.protobuf import json_format as _json_format
27
28# exports Summary, SummaryDescription, Event, TaggedRunMetadata, SessionLog
29# pylint: disable=unused-import
30from tensorflow.core.framework.summary_pb2 import Summary
31from tensorflow.core.framework.summary_pb2 import SummaryDescription
32from tensorflow.core.framework.summary_pb2 import SummaryMetadata as _SummaryMetadata  # pylint: enable=unused-import
33from tensorflow.core.util.event_pb2 import Event
34from tensorflow.core.util.event_pb2 import SessionLog
35from tensorflow.core.util.event_pb2 import TaggedRunMetadata
36# pylint: enable=unused-import
37
38from tensorflow.python.distribute import summary_op_util as _distribute_summary_op_util
39from tensorflow.python.eager import context as _context
40from tensorflow.python.framework import constant_op as _constant_op
41from tensorflow.python.framework import dtypes as _dtypes
42from tensorflow.python.framework import ops as _ops
43from tensorflow.python.ops import gen_logging_ops as _gen_logging_ops
44from tensorflow.python.ops import gen_summary_ops as _gen_summary_ops  # pylint: disable=unused-import
45from tensorflow.python.ops import summary_op_util as _summary_op_util
46
47# exports FileWriter, FileWriterCache
48# pylint: disable=unused-import
49from tensorflow.python.summary.writer.writer import FileWriter
50from tensorflow.python.summary.writer.writer_cache import FileWriterCache
51# pylint: enable=unused-import
52
53from tensorflow.python.util import compat as _compat
54from tensorflow.python.util.tf_export import tf_export
55
56
57@tf_export(v1=['summary.scalar'])
58def scalar(name, tensor, collections=None, family=None):
59  """Outputs a `Summary` protocol buffer containing a single scalar value.
60
61  The generated Summary has a Tensor.proto containing the input Tensor.
62
63  Args:
64    name: A name for the generated node. Will also serve as the series name in
65      TensorBoard.
66    tensor: A real numeric Tensor containing a single value.
67    collections: Optional list of graph collections keys. The new summary op is
68      added to these collections. Defaults to `[GraphKeys.SUMMARIES]`.
69    family: Optional; if provided, used as the prefix of the summary tag name,
70      which controls the tab name used for display on Tensorboard.
71
72  Returns:
73    A scalar `Tensor` of type `string`. Which contains a `Summary` protobuf.
74
75  Raises:
76    ValueError: If tensor has the wrong shape or type.
77
78  @compatibility(TF2)
79  This API is not compatible with eager execution or `tf.function`. To migrate
80  to TF2, please use `tf.summary.scalar` instead. Please check
81  [Migrating tf.summary usage to
82  TF 2.0](https://www.tensorflow.org/tensorboard/migrate#in_tf_1x) for concrete
83  steps for migration. `tf.summary.scalar` can also log training metrics in
84  Keras, you can check [Logging training metrics in
85  Keras](https://www.tensorflow.org/tensorboard/scalars_and_keras) for detials.
86
87  #### How to Map Arguments
88
89  | TF1 Arg Name  | TF2 Arg Name    | Note                                   |
90  | :------------ | :-------------- | :------------------------------------- |
91  | `name`        | `name`          | -                                      |
92  | `tensor`      | `data`          | -                                      |
93  | -             | `step`          | Explicit int64-castable monotonic step |
94  :               :                 : value. If omitted, this defaults to    :
95  :               :                 : `tf.summary.experimental.get_step()`.  :
96  | `collections` | Not Supported   | -                                      |
97  | `family`      | Removed         | Please use `tf.name_scope` instead to  |
98  :               :                 : manage summary name prefix.            :
99  | -             | `description`   | Optional long-form `str` description   |
100  :               :                 : for the summary. Markdown is supported.:
101  :               :                 : Defaults to empty.                     :
102
103  @end_compatibility
104  """
105  if _distribute_summary_op_util.skip_summary():
106    return _constant_op.constant('')
107  with _summary_op_util.summary_scope(
108      name, family, values=[tensor]) as (tag, scope):
109    val = _gen_logging_ops.scalar_summary(tags=tag, values=tensor, name=scope)
110    _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES])
111  return val
112
113
114@tf_export(v1=['summary.image'])
115def image(name, tensor, max_outputs=3, collections=None, family=None):
116  """Outputs a `Summary` protocol buffer with images.
117
118  The summary has up to `max_outputs` summary values containing images. The
119  images are built from `tensor` which must be 4-D with shape `[batch_size,
120  height, width, channels]` and where `channels` can be:
121
122  *  1: `tensor` is interpreted as Grayscale.
123  *  3: `tensor` is interpreted as RGB.
124  *  4: `tensor` is interpreted as RGBA.
125
126  The images have the same number of channels as the input tensor. For float
127  input, the values are normalized one image at a time to fit in the range
128  `[0, 255]`.  `uint8` values are unchanged.  The op uses two different
129  normalization algorithms:
130
131  *  If the input values are all positive, they are rescaled so the largest one
132     is 255.
133
134  *  If any input value is negative, the values are shifted so input value 0.0
135     is at 127.  They are then rescaled so that either the smallest value is 0,
136     or the largest one is 255.
137
138  The `tag` in the outputted Summary.Value protobufs is generated based on the
139  name, with a suffix depending on the max_outputs setting:
140
141  *  If `max_outputs` is 1, the summary value tag is '*name*/image'.
142  *  If `max_outputs` is greater than 1, the summary value tags are
143     generated sequentially as '*name*/image/0', '*name*/image/1', etc.
144
145  Args:
146    name: A name for the generated node. Will also serve as a series name in
147      TensorBoard.
148    tensor: A 4-D `uint8` or `float32` `Tensor` of shape `[batch_size, height,
149      width, channels]` where `channels` is 1, 3, or 4.
150    max_outputs: Max number of batch elements to generate images for.
151    collections: Optional list of ops.GraphKeys.  The collections to add the
152      summary to.  Defaults to [_ops.GraphKeys.SUMMARIES]
153    family: Optional; if provided, used as the prefix of the summary tag name,
154      which controls the tab name used for display on Tensorboard.
155
156  Returns:
157    A scalar `Tensor` of type `string`. The serialized `Summary` protocol
158    buffer.
159
160  @compatibility(TF2)
161  This API is not compatible with eager execution and `tf.function`. To migrate
162  to TF2, please use `tf.summary.image` instead. Please check
163  [Migrating tf.summary usage to
164  TF 2.0](https://www.tensorflow.org/tensorboard/migrate#in_tf_1x) for concrete
165  steps for migration.
166
167  #### How to Map Arguments
168
169  | TF1 Arg Name  | TF2 Arg Name    | Note                                   |
170  | :------------ | :-------------- | :------------------------------------- |
171  | `name`        | `name`          | -                                      |
172  | `tensor`      | `data`          | -                                      |
173  | -             | `step`          | Explicit int64-castable monotonic step |
174  :               :                 : value. If omitted, this defaults to    :
175  :               :                 : `tf.summary.experimental.get_step()`.  :
176  | `max_outputs` | `max_outputs`   | -                                      |
177  | `collections` | Not Supported   | -                                      |
178  | `family`      | Removed         | Please use `tf.name_scope` instead     |
179  :               :                 : to manage summary name prefix.         :
180  | -             | `description`   | Optional long-form `str` description   |
181  :               :                 : for the summary. Markdown is supported.:
182  :               :                 : Defaults to empty.                     :
183
184  @end_compatibility
185  """
186  if _distribute_summary_op_util.skip_summary():
187    return _constant_op.constant('')
188  with _summary_op_util.summary_scope(
189      name, family, values=[tensor]) as (tag, scope):
190    val = _gen_logging_ops.image_summary(
191        tag=tag, tensor=tensor, max_images=max_outputs, name=scope)
192    _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES])
193  return val
194
195
196@tf_export(v1=['summary.histogram'])
197def histogram(name, values, collections=None, family=None):
198  # pylint: disable=line-too-long
199  """Outputs a `Summary` protocol buffer with a histogram.
200
201  Adding a histogram summary makes it possible to visualize your data's
202  distribution in TensorBoard. You can see a detailed explanation of the
203  TensorBoard histogram dashboard
204  [here](https://www.tensorflow.org/get_started/tensorboard_histograms).
205
206  The generated
207  [`Summary`](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto)
208  has one summary value containing a histogram for `values`.
209
210  This op reports an `InvalidArgument` error if any value is not finite.
211
212  Args:
213    name: A name for the generated node. Will also serve as a series name in
214      TensorBoard.
215    values: A real numeric `Tensor`. Any shape. Values to use to
216      build the histogram.
217    collections: Optional list of graph collections keys. The new summary op is
218      added to these collections. Defaults to `[GraphKeys.SUMMARIES]`.
219    family: Optional; if provided, used as the prefix of the summary tag name,
220      which controls the tab name used for display on Tensorboard.
221
222  Returns:
223    A scalar `Tensor` of type `string`. The serialized `Summary` protocol
224    buffer.
225
226  @compatibility(TF2)
227  This API is not compatible with eager execution and `tf.function`. To migrate
228  to TF2, please use `tf.summary.histogram` instead. Please check
229  [Migrating tf.summary usage to
230  TF 2.0](https://www.tensorflow.org/tensorboard/migrate#in_tf_1x) for concrete
231  steps for migration.
232
233  #### How to Map Arguments
234
235  | TF1 Arg Name  | TF2 Arg Name    | Note                                   |
236  | :------------ | :-------------- | :------------------------------------- |
237  | `name`        | `name`          | -                                      |
238  | `values`      | `data`          | -                                      |
239  | -             | `step`          | Explicit int64-castable monotonic step |
240  :               :                 : value. If omitted, this defaults to    :
241  :               :                 : `tf.summary.experimental.get_step()`   :
242  | -             | `buckets`       | Optional positive `int` specifying     |
243  :               :                 : the histogram bucket number.           :
244  | `collections` | Not Supported   | -                                      |
245  | `family`      | Removed         | Please use `tf.name_scope` instead     |
246  :               :                 : to manage summary name prefix.         :
247  | -             | `description`   | Optional long-form `str` description   |
248  :               :                 : for the summary. Markdown is supported.:
249  :               :                 : Defaults to empty.                     :
250
251  @end_compatibility
252  """
253  if _distribute_summary_op_util.skip_summary():
254    return _constant_op.constant('')
255  with _summary_op_util.summary_scope(
256      name, family, values=[values],
257      default_name='HistogramSummary') as (tag, scope):
258    val = _gen_logging_ops.histogram_summary(
259        tag=tag, values=values, name=scope)
260    _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES])
261  return val
262
263
264@tf_export(v1=['summary.audio'])
265def audio(name, tensor, sample_rate, max_outputs=3, collections=None,
266          family=None):
267  # pylint: disable=line-too-long
268  """Outputs a `Summary` protocol buffer with audio.
269
270  The summary has up to `max_outputs` summary values containing audio. The
271  audio is built from `tensor` which must be 3-D with shape `[batch_size,
272  frames, channels]` or 2-D with shape `[batch_size, frames]`. The values are
273  assumed to be in the range of `[-1.0, 1.0]` with a sample rate of
274  `sample_rate`.
275
276  The `tag` in the outputted Summary.Value protobufs is generated based on the
277  name, with a suffix depending on the max_outputs setting:
278
279  *  If `max_outputs` is 1, the summary value tag is '*name*/audio'.
280  *  If `max_outputs` is greater than 1, the summary value tags are
281     generated sequentially as '*name*/audio/0', '*name*/audio/1', etc
282
283  Args:
284    name: A name for the generated node. Will also serve as a series name in
285      TensorBoard.
286    tensor: A 3-D `float32` `Tensor` of shape `[batch_size, frames, channels]`
287      or a 2-D `float32` `Tensor` of shape `[batch_size, frames]`.
288    sample_rate: A Scalar `float32` `Tensor` indicating the sample rate of the
289      signal in hertz.
290    max_outputs: Max number of batch elements to generate audio for.
291    collections: Optional list of ops.GraphKeys.  The collections to add the
292      summary to.  Defaults to [_ops.GraphKeys.SUMMARIES]
293    family: Optional; if provided, used as the prefix of the summary tag name,
294      which controls the tab name used for display on Tensorboard.
295
296  Returns:
297    A scalar `Tensor` of type `string`. The serialized `Summary` protocol
298    buffer.
299
300  @compatibility(TF2)
301  This API is not compatible with eager execution or `tf.function`. To migrate
302  to TF2, please use `tf.summary.audio` instead. Please check
303  [Migrating tf.summary usage to
304  TF 2.0](https://www.tensorflow.org/tensorboard/migrate#in_tf_1x) for concrete
305  steps for migration.
306
307  #### How to Map Arguments
308
309  | TF1 Arg Name  | TF2 Arg Name    | Note                                   |
310  | :------------ | :-------------- | :------------------------------------- |
311  | `name`        | `name`          | -                                      |
312  | `tensor`      | `data`          | Input for this argument now must be    |
313  :               :                 : three-dimensional `[k, t, c]`, where   :
314  :               :                 : `k` is the number of audio clips, `t`  :
315  :               :                 : is the number of frames, and `c` is    :
316  :               :                 : the number of channels. Two-dimensional:
317  :               :                 : input is no longer supported.          :
318  | `sample_rate` | `sample_rate`   | -                                      |
319  | -             | `step`          | Explicit int64-castable monotonic step |
320  :               :                 : value. If omitted, this defaults to    :
321  :               :                 : `tf.summary.experimental.get_step()`.  :
322  | `max_outputs` | `max_outputs`   | -                                      |
323  | `collections` | Not Supported   | -                                      |
324  | `family`      | Removed         | Please use `tf.name_scope` instead to  |
325  :               :                 : manage summary name prefix.            :
326  | -             | `encoding`      | Optional constant str for the desired  |
327  :               :                 : encoding. Check the docs for           :
328  :               :                 : `tf.summary.audio` for latest supported:
329  :               :                 : audio formats.                         :
330  | -             | `description`   | Optional long-form `str` description   |
331  :               :                 : for the summary. Markdown is supported.:
332  :               :                 : Defaults to empty.                     :
333
334  @end_compatibility
335  """
336  if _distribute_summary_op_util.skip_summary():
337    return _constant_op.constant('')
338  with _summary_op_util.summary_scope(
339      name, family=family, values=[tensor]) as (tag, scope):
340    sample_rate = _ops.convert_to_tensor(
341        sample_rate, dtype=_dtypes.float32, name='sample_rate')
342    val = _gen_logging_ops.audio_summary_v2(
343        tag=tag, tensor=tensor, max_outputs=max_outputs,
344        sample_rate=sample_rate, name=scope)
345    _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES])
346  return val
347
348
349@tf_export(v1=['summary.text'])
350def text(name, tensor, collections=None):
351  """Summarizes textual data.
352
353  Text data summarized via this plugin will be visible in the Text Dashboard
354  in TensorBoard. The standard TensorBoard Text Dashboard will render markdown
355  in the strings, and will automatically organize 1d and 2d tensors into tables.
356  If a tensor with more than 2 dimensions is provided, a 2d subarray will be
357  displayed along with a warning message. (Note that this behavior is not
358  intrinsic to the text summary api, but rather to the default TensorBoard text
359  plugin.)
360
361  Args:
362    name: A name for the generated node. Will also serve as a series name in
363      TensorBoard.
364    tensor: a string-type Tensor to summarize.
365    collections: Optional list of ops.GraphKeys.  The collections to add the
366      summary to.  Defaults to [_ops.GraphKeys.SUMMARIES]
367
368  Returns:
369    A TensorSummary op that is configured so that TensorBoard will recognize
370    that it contains textual data. The TensorSummary is a scalar `Tensor` of
371    type `string` which contains `Summary` protobufs.
372
373  Raises:
374    ValueError: If tensor has the wrong type.
375
376  @compatibility(TF2)
377  This API is not compatible with eager execution or `tf.function`. To migrate
378  to TF2, please use `tf.summary.text` instead. Please check
379  [Migrating tf.summary usage to
380  TF 2.0](https://www.tensorflow.org/tensorboard/migrate#in_tf_1x) for concrete
381  steps for migration.
382
383  #### How to Map Arguments
384
385  | TF1 Arg Name  | TF2 Arg Name    | Note                                   |
386  | :------------ | :-------------- | :------------------------------------- |
387  | `name`        | `name`          | -                                      |
388  | `tensor`      | `data`          | -                                      |
389  | -             | `step`          | Explicit int64-castable monotonic step |
390  :               :                 : value. If omitted, this defaults to    :
391  :               :                 : `tf.summary.experimental.get_step()`.  :
392  | `collections` | Not Supported   | -                                      |
393  | -             | `description`   | Optional long-form `str` description   |
394  :               :                 : for the summary. Markdown is supported.:
395  :               :                 : Defaults to empty.                     :
396
397  @end_compatibility
398  """
399  if tensor.dtype != _dtypes.string:
400    raise ValueError('Expected tensor %s to have dtype string, got %s' %
401                     (tensor.name, tensor.dtype))
402
403  summary_metadata = _SummaryMetadata(
404      plugin_data=_SummaryMetadata.PluginData(plugin_name='text'))
405  t_summary = tensor_summary(
406      name=name,
407      tensor=tensor,
408      summary_metadata=summary_metadata,
409      collections=collections)
410  return t_summary
411
412
413@tf_export(v1=['summary.tensor_summary'])
414def tensor_summary(name,
415                   tensor,
416                   summary_description=None,
417                   collections=None,
418                   summary_metadata=None,
419                   family=None,
420                   display_name=None):
421  """Outputs a `Summary` protocol buffer with a serialized tensor.proto.
422
423  Args:
424    name: A name for the generated node. If display_name is not set, it will
425      also serve as the tag name in TensorBoard. (In that case, the tag
426      name will inherit tf name scopes.)
427    tensor: A tensor of any type and shape to serialize.
428    summary_description: A long description of the summary sequence. Markdown
429      is supported.
430    collections: Optional list of graph collections keys. The new summary op is
431      added to these collections. Defaults to `[GraphKeys.SUMMARIES]`.
432    summary_metadata: Optional SummaryMetadata proto (which describes which
433      plugins may use the summary value).
434    family: Optional; if provided, used as the prefix of the summary tag,
435      which controls the name used for display on TensorBoard when
436      display_name is not set.
437    display_name: A string used to name this data in TensorBoard. If this is
438      not set, then the node name will be used instead.
439
440  Returns:
441    A scalar `Tensor` of type `string`. The serialized `Summary` protocol
442    buffer.
443  """
444
445  if summary_metadata is None:
446    summary_metadata = _SummaryMetadata()
447
448  if summary_description is not None:
449    summary_metadata.summary_description = summary_description
450
451  if display_name is not None:
452    summary_metadata.display_name = display_name
453
454  serialized_summary_metadata = summary_metadata.SerializeToString()
455
456  if _distribute_summary_op_util.skip_summary():
457    return _constant_op.constant('')
458  with _summary_op_util.summary_scope(
459      name, family, values=[tensor]) as (tag, scope):
460    val = _gen_logging_ops.tensor_summary_v2(
461        tensor=tensor,
462        tag=tag,
463        name=scope,
464        serialized_summary_metadata=serialized_summary_metadata)
465    _summary_op_util.collect(val, collections, [_ops.GraphKeys.SUMMARIES])
466  return val
467
468
469@tf_export(v1=['summary.merge'])
470def merge(inputs, collections=None, name=None):
471  # pylint: disable=line-too-long
472  """Merges summaries.
473
474  This op creates a
475  [`Summary`](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto)
476  protocol buffer that contains the union of all the values in the input
477  summaries.
478
479  When the Op is run, it reports an `InvalidArgument` error if multiple values
480  in the summaries to merge use the same tag.
481
482  Args:
483    inputs: A list of `string` `Tensor` objects containing serialized `Summary`
484      protocol buffers.
485    collections: Optional list of graph collections keys. The new summary op is
486      added to these collections. Defaults to `[]`.
487    name: A name for the operation (optional).
488
489  Returns:
490    A scalar `Tensor` of type `string`. The serialized `Summary` protocol
491    buffer resulting from the merging.
492
493  Raises:
494    RuntimeError: If called with eager mode enabled.
495
496  @compatibility(TF2)
497  This API is not compatible with eager execution or `tf.function`. To migrate
498  to TF2, this API can be omitted entirely, because in TF2 individual summary
499  ops, like `tf.summary.scalar()`, write directly to the default summary writer
500  if one is active. Thus, it's not necessary to merge summaries or to manually
501  add the resulting merged summary output to the writer. See the usage example
502  shown below.
503
504  For a comprehensive `tf.summary` migration guide, please follow
505  [Migrating tf.summary usage to
506  TF 2.0](https://www.tensorflow.org/tensorboard/migrate#in_tf_1x).
507
508  #### TF1 & TF2 Usage Example
509
510  TF1:
511
512  ```python
513  dist = tf.compat.v1.placeholder(tf.float32, [100])
514  tf.compat.v1.summary.histogram(name="distribution", values=dist)
515  writer = tf.compat.v1.summary.FileWriter("/tmp/tf1_summary_example")
516  summaries = tf.compat.v1.summary.merge_all()
517
518  sess = tf.compat.v1.Session()
519  for step in range(100):
520    mean_moving_normal = np.random.normal(loc=step, scale=1, size=[100])
521    summ = sess.run(summaries, feed_dict={dist: mean_moving_normal})
522    writer.add_summary(summ, global_step=step)
523  ```
524
525  TF2:
526
527  ```python
528  writer = tf.summary.create_file_writer("/tmp/tf2_summary_example")
529  for step in range(100):
530    mean_moving_normal = np.random.normal(loc=step, scale=1, size=[100])
531    with writer.as_default(step=step):
532      tf.summary.histogram(name='distribution', data=mean_moving_normal)
533  ```
534
535  @end_compatibility
536  """
537  # pylint: enable=line-too-long
538  if _context.executing_eagerly():
539    raise RuntimeError(
540        'Merging tf.summary.* ops is not compatible with eager execution. '
541        'Use tf.contrib.summary instead.')
542  if _distribute_summary_op_util.skip_summary():
543    return _constant_op.constant('')
544  name = _summary_op_util.clean_tag(name)
545  with _ops.name_scope(name, 'Merge', inputs):
546    val = _gen_logging_ops.merge_summary(inputs=inputs, name=name)
547    _summary_op_util.collect(val, collections, [])
548  return val
549
550
551@tf_export(v1=['summary.merge_all'])
552def merge_all(key=_ops.GraphKeys.SUMMARIES, scope=None, name=None):
553  """Merges all summaries collected in the default graph.
554
555  Args:
556    key: `GraphKey` used to collect the summaries.  Defaults to
557      `GraphKeys.SUMMARIES`.
558    scope: Optional scope used to filter the summary ops, using `re.match`.
559    name: A name for the operation (optional).
560
561  Returns:
562    If no summaries were collected, returns None.  Otherwise returns a scalar
563    `Tensor` of type `string` containing the serialized `Summary` protocol
564    buffer resulting from the merging.
565
566  Raises:
567    RuntimeError: If called with eager execution enabled.
568
569  @compatibility(TF2)
570  This API is not compatible with eager execution or `tf.function`. To migrate
571  to TF2, this API can be omitted entirely, because in TF2 individual summary
572  ops, like `tf.summary.scalar()`, write directly to the default summary writer
573  if one is active. Thus, it's not necessary to merge summaries or to manually
574  add the resulting merged summary output to the writer. See the usage example
575  shown below.
576
577  For a comprehensive `tf.summary` migration guide, please follow
578  [Migrating tf.summary usage to
579  TF 2.0](https://www.tensorflow.org/tensorboard/migrate#in_tf_1x).
580
581  #### TF1 & TF2 Usage Example
582
583  TF1:
584
585  ```python
586  dist = tf.compat.v1.placeholder(tf.float32, [100])
587  tf.compat.v1.summary.histogram(name="distribution", values=dist)
588  writer = tf.compat.v1.summary.FileWriter("/tmp/tf1_summary_example")
589  summaries = tf.compat.v1.summary.merge_all()
590
591  sess = tf.compat.v1.Session()
592  for step in range(100):
593    mean_moving_normal = np.random.normal(loc=step, scale=1, size=[100])
594    summ = sess.run(summaries, feed_dict={dist: mean_moving_normal})
595    writer.add_summary(summ, global_step=step)
596  ```
597
598  TF2:
599
600  ```python
601  writer = tf.summary.create_file_writer("/tmp/tf2_summary_example")
602  for step in range(100):
603    mean_moving_normal = np.random.normal(loc=step, scale=1, size=[100])
604    with writer.as_default(step=step):
605      tf.summary.histogram(name='distribution', data=mean_moving_normal)
606  ```
607
608  @end_compatibility
609  """
610  if _context.executing_eagerly():
611    raise RuntimeError(
612        'Merging tf.summary.* ops is not compatible with eager execution. '
613        'Use tf.contrib.summary instead.')
614  summary_ops = _ops.get_collection(key, scope=scope)
615  if not summary_ops:
616    return None
617  else:
618    return merge(summary_ops, name=name)
619
620
621@tf_export(v1=['summary.get_summary_description'])
622def get_summary_description(node_def):
623  """Given a TensorSummary node_def, retrieve its SummaryDescription.
624
625  When a Summary op is instantiated, a SummaryDescription of associated
626  metadata is stored in its NodeDef. This method retrieves the description.
627
628  Args:
629    node_def: the node_def_pb2.NodeDef of a TensorSummary op
630
631  Returns:
632    a summary_pb2.SummaryDescription
633
634  Raises:
635    ValueError: if the node is not a summary op.
636
637  @compatibility(eager)
638  Not compatible with eager execution. To write TensorBoard
639  summaries under eager execution, use `tf.contrib.summary` instead.
640  @end_compatibility
641  """
642
643  if node_def.op != 'TensorSummary':
644    raise ValueError("Can't get_summary_description on %s" % node_def.op)
645  description_str = _compat.as_str_any(node_def.attr['description'].s)
646  summary_description = SummaryDescription()
647  _json_format.Parse(description_str, summary_description)
648  return summary_description
649