Spaces:
Running
Running
# Copyright 2018 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 the TFExampleDecoder. | |
The TFExampleDecode is a DataDecoder used to decode TensorFlow Example protos. | |
In order to do so each requested item must be paired with one or more Example | |
features that are parsed to produce the Tensor-based manifestation of the item. | |
""" | |
import tensorflow as tf | |
slim = tf.contrib.slim | |
data_decoder = slim.data_decoder | |
class TFSequenceExampleDecoder(data_decoder.DataDecoder): | |
"""A decoder for TensorFlow SequenceExamples. | |
Decoding SequenceExample proto buffers is comprised of two stages: | |
(1) Example parsing and (2) tensor manipulation. | |
In the first stage, the tf.parse_single_sequence_example function is called | |
with a list of FixedLenFeatures and SparseLenFeatures. These instances tell TF | |
how to parse the example. The output of this stage is a set of tensors. | |
In the second stage, the resulting tensors are manipulated to provide the | |
requested 'item' tensors. | |
To perform this decoding operation, a SequenceExampleDecoder is given a list | |
of ItemHandlers. Each ItemHandler indicates the set of features for stage 1 | |
and contains the instructions for post_processing its tensors for stage 2. | |
""" | |
def __init__(self, keys_to_context_features, keys_to_sequence_features, | |
items_to_handlers): | |
"""Constructs the decoder. | |
Args: | |
keys_to_context_features: a dictionary from TF-SequenceExample context | |
keys to either tf.VarLenFeature or tf.FixedLenFeature instances. | |
See tensorflow's parsing_ops.py. | |
keys_to_sequence_features: a dictionary from TF-SequenceExample sequence | |
keys to either tf.VarLenFeature or tf.FixedLenSequenceFeature instances. | |
See tensorflow's parsing_ops.py. | |
items_to_handlers: a dictionary from items (strings) to ItemHandler | |
instances. Note that the ItemHandler's are provided the keys that they | |
use to return the final item Tensors. | |
Raises: | |
ValueError: if the same key is present for context features and sequence | |
features. | |
""" | |
unique_keys = set() | |
unique_keys.update(keys_to_context_features) | |
unique_keys.update(keys_to_sequence_features) | |
if len(unique_keys) != ( | |
len(keys_to_context_features) + len(keys_to_sequence_features)): | |
# This situation is ambiguous in the decoder's keys_to_tensors variable. | |
raise ValueError('Context and sequence keys are not unique. \n' | |
' Context keys: %s \n Sequence keys: %s' % | |
(list(keys_to_context_features.keys()), | |
list(keys_to_sequence_features.keys()))) | |
self._keys_to_context_features = keys_to_context_features | |
self._keys_to_sequence_features = keys_to_sequence_features | |
self._items_to_handlers = items_to_handlers | |
def list_items(self): | |
"""See base class.""" | |
return self._items_to_handlers.keys() | |
def decode(self, serialized_example, items=None): | |
"""Decodes the given serialized TF-SequenceExample. | |
Args: | |
serialized_example: a serialized TF-SequenceExample tensor. | |
items: the list of items to decode. These must be a subset of the item | |
keys in self._items_to_handlers. If `items` is left as None, then all | |
of the items in self._items_to_handlers are decoded. | |
Returns: | |
the decoded items, a list of tensor. | |
""" | |
context, feature_list = tf.parse_single_sequence_example( | |
serialized_example, self._keys_to_context_features, | |
self._keys_to_sequence_features) | |
# Reshape non-sparse elements just once: | |
for k in self._keys_to_context_features: | |
v = self._keys_to_context_features[k] | |
if isinstance(v, tf.FixedLenFeature): | |
context[k] = tf.reshape(context[k], v.shape) | |
if not items: | |
items = self._items_to_handlers.keys() | |
outputs = [] | |
for item in items: | |
handler = self._items_to_handlers[item] | |
keys_to_tensors = { | |
key: context[key] if key in context else feature_list[key] | |
for key in handler.keys | |
} | |
outputs.append(handler.tensors_to_item(keys_to_tensors)) | |
return outputs | |