def scalar_pb(tag, tensor, description=None): """Create a scalar tf.Summary protobuf. Arguments: tag: String tag for the summary. tensor: A rank-0 `np.array` or a compatible python number type. description: Optional long-form description for this summary, as a `str`. Markdown is supported. Defaults to empty. Returns: A `tf.Summary` protobuf object. """ arr = np.array(tensor) if arr.shape != (): raise ValueError('Expected scalar shape for tensor, got shape: %s.' % arr.shape) if arr.dtype.kind not in ('b', 'i', 'u', 'f'): # bool, int, uint, float raise ValueError('Cast %s to float is not supported' % arr.dtype.name) tensor_proto = tf.make_tensor_proto(arr.astype(np.float32)) summary_metadata = metadata.create_summary_metadata( display_name=None, description=description) summary = tf.Summary() summary.value.add(tag=tag, metadata=summary_metadata, tensor=tensor_proto) return summary
def pb(name, data, display_name=None, description=None): """Create a legacy scalar summary protobuf. Arguments: name: A unique name for the generated summary, including any desired name scopes. data: A rank-0 `np.array` or array-like form (so raw `int`s and `float`s are fine, too). display_name: Optional name for this summary in TensorBoard, as a `str`. Defaults to `name`. description: Optional long-form description for this summary, as a `str`. Markdown is supported. Defaults to empty. Returns: A `tf.Summary` protobuf object. """ data = np.array(data) if data.shape != (): raise ValueError('Expected scalar shape for data, saw shape: %s.' % data.shape) if data.dtype.kind not in ('b', 'i', 'u', 'f'): # bool, int, uint, float raise ValueError('Cast %s to float is not supported' % data.dtype.name) tensor = tf.make_tensor_proto(data.astype(np.float32)) if display_name is None: display_name = name summary_metadata = metadata.create_summary_metadata( display_name=display_name, description=description) summary = tf.Summary() summary.value.add(tag='%s/scalar_summary' % name, metadata=summary_metadata, tensor=tensor) return summary
def raw_data_pb(name, true_positive_counts, false_positive_counts, true_negative_counts, false_negative_counts, precision, recall, num_thresholds=None, display_name=None, description=None): """Create a PR curves summary protobuf from raw data values. Args: name: A tag attached to the summary. Used by TensorBoard for organization. true_positive_counts: A rank-1 numpy array of true positive counts. Must contain `num_thresholds` elements and be castable to float32. false_positive_counts: A rank-1 numpy array of false positive counts. Must contain `num_thresholds` elements and be castable to float32. true_negative_counts: A rank-1 numpy array of true negative counts. Must contain `num_thresholds` elements and be castable to float32. false_negative_counts: A rank-1 numpy array of false negative counts. Must contain `num_thresholds` elements and be castable to float32. precision: A rank-1 numpy array of precision values. Must contain `num_thresholds` elements and be castable to float32. recall: A rank-1 numpy array of recall values. Must contain `num_thresholds` elements and be castable to float32. num_thresholds: Number of thresholds, evenly distributed in `[0, 1]`, to compute PR metrics for. Should be an int `>= 2`. display_name: Optional name for this summary in TensorBoard, as a `str`. Defaults to `name`. description: Optional long-form description for this summary, as a `str`. Markdown is supported. Defaults to empty. Returns: A summary operation for use in a TensorFlow graph. See docs for the `op` method for details on the float32 tensor produced by this summary. """ if display_name is None: display_name = name summary_metadata = metadata.create_summary_metadata( display_name=display_name if display_name is not None else name, description=description or '', num_thresholds=num_thresholds) summary = tf.Summary() data = np.stack( (true_positive_counts, false_positive_counts, true_negative_counts, false_negative_counts, precision, recall)) tensor = tf.make_tensor_proto(np.float32(data), dtype=tf.float32) summary.value.add(tag='%s/pr_curves' % name, metadata=summary_metadata, tensor=tensor) return summary
def AddScalarTensor(self, tag, wall_time=0, step=0, value=0): """Add a rank-0 tensor event. Note: This is not related to the scalar plugin; it's just a convenience function to add an event whose contents aren't important. """ tensor = tf.make_tensor_proto(float(value)) event = tf.Event( wall_time=wall_time, step=step, summary=tf.Summary( value=[tf.Summary.Value(tag=tag, tensor=tensor)])) self.AddEvent(event)
def normalize_summary_pb(self, pb): """Pass `pb`'s `TensorProto` through a marshalling roundtrip. `TensorProto`s can be equal in value even if they are not identical in representation, because data can be stored in either the `tensor_content` field or the `${dtype}_value` field. This normalization ensures a canonical form, and should be used before comparing two `Summary`s for equality. """ result = tf.Summary() result.MergeFrom(pb) for value in result.value: if value.HasField('tensor'): new_tensor = tf.make_tensor_proto(tf.make_ndarray( value.tensor)) value.ClearField('tensor') value.tensor.MergeFrom(new_tensor) return result
def pb(name, images, max_outputs=3, display_name=None, description=None): """Create an image summary protobuf. This behaves as if you were to create an `op` with the same arguments (wrapped with constant tensors where appropriate) and then execute that summary op in a TensorFlow session. Arguments: name: A unique name for the generated summary, including any desired name scopes. images: An `np.array` representing pixel data with shape `[k, h, w, c]`, where `k` is the number of images, `w` and `h` are the width and height of the images, and `c` is the number of channels, which should be 1, 3, or 4. max_outputs: Optional `int`. At most this many images will be emitted. If more than this many images are provided, the first `max_outputs` many images will be used and the rest silently discarded. display_name: Optional name for this summary in TensorBoard, as a `str`. Defaults to `name`. description: Optional long-form description for this summary, as a `str`. Markdown is supported. Defaults to empty. Returns: A `tf.Summary` protobuf object. """ images = np.array(images).astype(np.uint8) if images.ndim != 4: raise ValueError('Shape %r must have rank 4' % (images.shape, )) limited_images = images[:max_outputs] encoded_images = [util.encode_png(image) for image in limited_images] (width, height) = (images.shape[2], images.shape[1]) content = [str(width), str(height)] + encoded_images tensor = tf.make_tensor_proto(content, dtype=tf.string) if display_name is None: display_name = name summary_metadata = metadata.create_summary_metadata( display_name=display_name, description=description) summary = tf.Summary() summary.value.add(tag='%s/image_summary' % name, metadata=summary_metadata, tensor=tensor) return summary
def make_tensor_proto(values, dtype=None, shape=None, verify_shape=False): """Create a TensorProto. Args: values: Values to put in the TensorProto. dtype: Optional tensor_pb2 DataType value. shape: List of integers representing the dimensions of tensor. verify_shape: Boolean that enables verification of a shape of values. Returns: A `TensorProto`. Depending on the type, it may contain data in the "tensor_content" attribute, which is not directly useful to Python programs. To access the values you should convert the proto back to a numpy ndarray with `tensor_util.MakeNdarray(proto)`. If `values` is a `TensorProto`, it is immediately returned; `dtype` and `shape` are ignored. Raises: TypeError: if unsupported types are provided. ValueError: if arguments have inappropriate values or if verify_shape is True and shape of values is not equals to a shape from the argument. make_tensor_proto accepts "values" of a python scalar, a python list, a numpy ndarray, or a numpy scalar. If "values" is a python scalar or a python list, make_tensor_proto first convert it to numpy ndarray. If dtype is None, the conversion tries its best to infer the right numpy data type. Otherwise, the resulting numpy array has a convertible data type with the given dtype. In either case above, the numpy ndarray (either the caller provided or the auto converted) must have the convertible type with dtype. make_tensor_proto then converts the numpy array to a tensor proto. If "shape" is None, the resulting tensor proto represents the numpy array precisely. Otherwise, "shape" specifies the tensor's shape and the numpy array can not have more elements than what "shape" specifies. """ return tf.make_tensor_proto(values, dtype, shape, verify_shape)
def _writeMetadata(self, logdir, summary_metadata, nonce=''): """Write to disk a summary with the given metadata. Arguments: logdir: a string summary_metadata: a `SummaryMetadata` protobuf object nonce: optional; will be added to the end of the event file name to guarantee that multiple calls to this function do not stomp the same file """ summary = tf.Summary() summary.value.add(tensor=tf.make_tensor_proto(['po', 'ta', 'to'], dtype=tf.string), tag='you_are_it', metadata=summary_metadata) writer = tf.summary.FileWriter(logdir, filename_suffix=nonce) writer.add_summary(summary.SerializeToString()) writer.close()
def pb(scalars_layout): """Creates a summary that contains a layout. When users navigate to the custom scalars dashboard, they will see a layout based on the proto provided to this function. Args: scalars_layout: The scalars_layout_pb2.Layout proto that specifies the layout. Returns: A summary proto containing the layout. """ assert isinstance(scalars_layout, layout_pb2.Layout) tensor = tf.make_tensor_proto( scalars_layout.SerializeToString(), dtype=tf.string) summary = tf.Summary() summary.value.add(tag=metadata.CONFIG_SUMMARY_TAG, metadata=_create_summary_metadata(), tensor=tensor) return summary
def make_summary(tag, metadata, data): tensor_proto = tf.make_tensor_proto(data) return tf.Summary.Value(tag=tag, metadata=metadata, tensor=tensor_proto)
def _mock_tensors(self, run, tag): result_dict = { 'session_1': { 'current_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(10.0)) ], 'delta_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(20.0)), TensorEvent(wall_time=10, step=2, tensor_proto=tf.make_tensor_proto(15.0)) ], 'optional_metric': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(20.0)), TensorEvent(wall_time=2, step=20, tensor_proto=tf.make_tensor_proto(33.0)) ] }, 'session_2': { 'current_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(100.0)), ], 'delta_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(200.0)), TensorEvent(wall_time=10, step=2, tensor_proto=tf.make_tensor_proto(150.0)) ] }, 'session_3': { 'current_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(1.0)), ], 'delta_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(2.0)), TensorEvent(wall_time=10, step=2, tensor_proto=tf.make_tensor_proto(1.5)) ] }, 'session_4': { 'current_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(101.0)), ], 'delta_temp': [ TensorEvent(wall_time=1, step=1, tensor_proto=tf.make_tensor_proto(201.0)), TensorEvent(wall_time=10, step=2, tensor_proto=tf.make_tensor_proto(-151.0)) ] }, } return result_dict[run][tag]
def pb(name, audio, sample_rate, labels=None, max_outputs=3, encoding=None, display_name=None, description=None): """Create an audio summary protobuf. This behaves as if you were to create an `op` with the same arguments (wrapped with constant tensors where appropriate) and then execute that summary op in a TensorFlow session. Arguments: name: A unique name for the generated summary node. audio: An `np.array` representing audio data with shape `[k, t, c]`, where `k` is the number of audio clips, `t` is the number of frames, and `c` is the number of channels. Elements should be floating-point values in `[-1.0, 1.0]`. sample_rate: An `int` that represents the sample rate, in Hz. Must be positive. labels: Optional list (or rank-1 `np.array`) of textstrings or UTF-8 bytestrings whose length is the first dimension of `audio`, where `labels[i]` contains arbitrary textual information about `audio[i]`. (For instance, this could be some text that a TTS system was supposed to produce.) Markdown is supported. max_outputs: Optional `int`. At most this many audio clips will be emitted. When more than `max_outputs` many clips are provided, the first `max_outputs` many clips will be used and the rest silently discarded. encoding: A constant `str` indicating the desired encoding. You can choose any format you like, as long as it's "wav". Please see the "API compatibility note" below. display_name: Optional name for this summary in TensorBoard, as a `str`. Defaults to `name`. description: Optional long-form description for this summary, as a `str`. Markdown is supported. Defaults to empty. Returns: A `tf.Summary` protobuf object. API compatibility note: The default value of the `encoding` argument is _not_ guaranteed to remain unchanged across TensorBoard versions. In the future, we will by default encode as FLAC instead of as WAV. If the specific format is important to you, please provide a file format explicitly. """ audio = np.array(audio) if audio.ndim != 3: raise ValueError('Shape %r must have rank 3' % (audio.shape, )) if encoding is None: encoding = 'wav' if encoding == 'wav': encoding = metadata.Encoding.Value('WAV') encoder = functools.partial(util.encode_wav, samples_per_second=sample_rate) else: raise ValueError('Unknown encoding: %r' % encoding) limited_audio = audio[:max_outputs] if labels is None: limited_labels = [b''] * len(limited_audio) else: limited_labels = [ tf.compat.as_bytes(label) for label in labels[:max_outputs] ] encoded_audio = [encoder(a) for a in limited_audio] content = np.array([encoded_audio, limited_labels]).transpose() tensor = tf.make_tensor_proto(content, dtype=tf.string) if display_name is None: display_name = name summary_metadata = metadata.create_summary_metadata( display_name=display_name, description=description, encoding=encoding) summary = tf.Summary() summary.value.add(tag='%s/audio_summary' % name, metadata=summary_metadata, tensor=tensor) return summary
def pb(name, data, bucket_count=None, display_name=None, description=None): """Create a histogram summary protobuf. Arguments: name: A unique name for the generated summary, including any desired name scopes. data: A `np.array` or array-like form of any shape. Must have type castable to `float`. bucket_count: Optional positive `int`. The output will have this many buckets, except in two edge cases. If there is no data, then there are no buckets. If there is data but all points have the same value, then there is one bucket whose left and right endpoints are the same. display_name: Optional name for this summary in TensorBoard, as a `str`. Defaults to `name`. description: Optional long-form description for this summary, as a `str`. Markdown is supported. Defaults to empty. Returns: A `tf.Summary` protobuf object. """ if bucket_count is None: bucket_count = DEFAULT_BUCKET_COUNT data = np.array(data).flatten().astype(float) if data.size == 0: buckets = np.array([]).reshape((0, 3)) else: min_ = np.min(data) max_ = np.max(data) range_ = max_ - min_ if range_ == 0: center = min_ buckets = np.array([[center - 0.5, center + 0.5, float(data.size)]]) else: bucket_width = range_ / bucket_count offsets = data - min_ bucket_indices = np.floor(offsets / bucket_width).astype(int) clamped_indices = np.minimum(bucket_indices, bucket_count - 1) one_hots = (np.array([clamped_indices ]).transpose() == np.arange(0, bucket_count) ) # broadcast assert one_hots.shape == (data.size, bucket_count), (one_hots.shape, (data.size, bucket_count)) bucket_counts = np.sum(one_hots, axis=0) edges = np.linspace(min_, max_, bucket_count + 1) left_edges = edges[:-1] right_edges = edges[1:] buckets = np.array([left_edges, right_edges, bucket_counts]).transpose() tensor = tf.make_tensor_proto(buckets, dtype=tf.float64) if display_name is None: display_name = name summary_metadata = metadata.create_summary_metadata( display_name=display_name, description=description) summary = tf.Summary() summary.value.add(tag='%s/histogram_summary' % name, metadata=summary_metadata, tensor=tensor) return summary