Esempio n. 1
0
  def from_value(value):
    """Returns an `Optional` that wraps the given value.

    Args:
      value: A nested structure of `tf.Tensor` and/or `tf.SparseTensor` objects.

    Returns:
      An `Optional` that wraps `value`.
    """
    # TODO(b/110122868): Consolidate this destructuring logic with the
    # similar code in `Dataset.from_tensors()`.
    with ops.name_scope("optional") as scope:
      with ops.name_scope("value"):
        value = nest.pack_sequence_as(value, [
            sparse_tensor_lib.SparseTensor.from_value(t)
            if sparse_tensor_lib.is_sparse(t) else ops.convert_to_tensor(
                t, name="component_%d" % i)
            for i, t in enumerate(nest.flatten(value))
        ])

      encoded_value = nest.flatten(sparse.serialize_sparse_tensors(value))
      output_classes = sparse.get_classes(value)
      output_shapes = nest.pack_sequence_as(
          value, [t.get_shape() for t in nest.flatten(value)])
      output_types = nest.pack_sequence_as(
          value, [t.dtype for t in nest.flatten(value)])

    return _OptionalImpl(
        gen_dataset_ops.optional_from_value(encoded_value, name=scope),
        output_shapes, output_types, output_classes)
Esempio n. 2
0
    def tf_finalize_func(*args):
      """A wrapper for Defun that facilitates shape inference."""
      for arg, shape in zip(
          args,
          nest.flatten(
              sparse.as_dense_shapes(self._state_shapes, self._state_classes))):
        arg.set_shape(shape)

      nested_args = nest.pack_sequence_as(self._state_types, args)
      nested_args = sparse.deserialize_sparse_tensors(
          nested_args, self._state_types, self._state_shapes,
          self._state_classes)

      ret = finalize_func(nested_args)

      # Convert any `SparseTensorValue`s to `SparseTensor`s and all other
      # values to tensors.
      ret = nest.pack_sequence_as(ret, [
          sparse_tensor.SparseTensor.from_value(t)
          if sparse_tensor.is_sparse(t) else ops.convert_to_tensor(t)
          for t in nest.flatten(ret)
      ])

      self._output_classes = sparse.get_classes(ret)
      self._output_shapes = nest.pack_sequence_as(
          ret, [t.get_shape() for t in nest.flatten(ret)])
      self._output_types = nest.pack_sequence_as(
          ret, [t.dtype for t in nest.flatten(ret)])

      dataset_ops._warn_if_collections("tf.contrib.data.group_by_reducer()")  # pylint: disable=protected-access

      # Serialize any sparse tensors.
      ret = nest.pack_sequence_as(
          ret, [t for t in nest.flatten(sparse.serialize_sparse_tensors(ret))])
      return nest.flatten(ret)
Esempio n. 3
0
  def testFlattenAndPack(self):
    structure = ((3, 4), 5, (6, 7, (9, 10), 8))
    flat = ["a", "b", "c", "d", "e", "f", "g", "h"]
    self.assertEqual(nest.flatten(structure), [3, 4, 5, 6, 7, 9, 10, 8])
    self.assertEqual(
        nest.pack_sequence_as(structure, flat), (("a", "b"), "c",
                                                 ("d", "e", ("f", "g"), "h")))
    point = collections.namedtuple("Point", ["x", "y"])
    structure = (point(x=4, y=2), ((point(x=1, y=0),),))
    flat = [4, 2, 1, 0]
    self.assertEqual(nest.flatten(structure), flat)
    restructured_from_flat = nest.pack_sequence_as(structure, flat)
    self.assertEqual(restructured_from_flat, structure)
    self.assertEqual(restructured_from_flat[0].x, 4)
    self.assertEqual(restructured_from_flat[0].y, 2)
    self.assertEqual(restructured_from_flat[1][0][0].x, 1)
    self.assertEqual(restructured_from_flat[1][0][0].y, 0)

    self.assertEqual([5], nest.flatten(5))
    self.assertEqual([np.array([5])], nest.flatten(np.array([5])))

    self.assertEqual("a", nest.pack_sequence_as(5, ["a"]))
    self.assertEqual(
        np.array([5]), nest.pack_sequence_as("scalar", [np.array([5])]))

    with self.assertRaisesRegexp(ValueError, "Structure is a scalar"):
      nest.pack_sequence_as("scalar", [4, 5])

    with self.assertRaisesRegexp(TypeError, "flat_sequence"):
      nest.pack_sequence_as([4, 5], "bad_sequence")

    with self.assertRaises(ValueError):
      nest.pack_sequence_as([5, 6, [7, 8]], ["a", "b", "c"])
Esempio n. 4
0
    def tf_finalize_func(*args):
      """A wrapper for Defun that facilitates shape inference."""
      for arg, shape in zip(
          args,
          nest.flatten(
              sparse.as_dense_shapes(self._state_shapes, self._state_classes))):
        arg.set_shape(shape)

      nested_args = nest.pack_sequence_as(self._state_types, args)
      nested_args = sparse.deserialize_sparse_tensors(
          nested_args, self._state_types, self._state_shapes,
          self._state_classes)

      ret = finalize_func(nested_args)

      # Convert any `SparseTensorValue`s to `SparseTensor`s and all other
      # values to tensors.
      ret = nest.pack_sequence_as(ret, [
          sparse_tensor.SparseTensor.from_value(t)
          if sparse_tensor.is_sparse(t) else ops.convert_to_tensor(t)
          for t in nest.flatten(ret)
      ])

      self._output_classes = sparse.get_classes(ret)
      self._output_shapes = nest.pack_sequence_as(
          ret, [t.get_shape() for t in nest.flatten(ret)])
      self._output_types = nest.pack_sequence_as(
          ret, [t.dtype for t in nest.flatten(ret)])

      # Serialize any sparse tensors.
      ret = nest.pack_sequence_as(
          ret, [t for t in nest.flatten(sparse.serialize_sparse_tensors(ret))])
      return nest.flatten(ret)
Esempio n. 5
0
      def tf_reduce_func(*args):
        """A wrapper for Defun that facilitates shape inference."""
        for arg, shape in zip(
            args,
            nest.flatten(
                sparse.as_dense_shapes(self._state_shapes, self._state_classes))
            + nest.flatten(
                sparse.as_dense_shapes(input_dataset.output_shapes,
                                       input_dataset.output_classes))):
          arg.set_shape(shape)

        pivot = len(nest.flatten(self._state_shapes))
        nested_state_args = nest.pack_sequence_as(self._state_types,
                                                  args[:pivot])
        nested_state_args = sparse.deserialize_sparse_tensors(
            nested_state_args, self._state_types, self._state_shapes,
            self._state_classes)
        nested_input_args = nest.pack_sequence_as(input_dataset.output_types,
                                                  args[pivot:])
        nested_input_args = sparse.deserialize_sparse_tensors(
            nested_input_args, input_dataset.output_types,
            input_dataset.output_shapes, input_dataset.output_classes)

        ret = reduce_func(nested_state_args, nested_input_args)

        # Convert any `SparseTensorValue`s to `SparseTensor`s and all other
        # values to tensors.
        ret = nest.pack_sequence_as(ret, [
            sparse_tensor.SparseTensor.from_value(t)
            if sparse_tensor.is_sparse(t) else ops.convert_to_tensor(t)
            for t in nest.flatten(ret)
        ])

        # Extract shape information from the returned values.
        flat_new_state = nest.flatten(ret)
        flat_new_state_shapes.extend([t.get_shape() for t in flat_new_state])

        # Extract and validate type information from the returned values.
        for t, dtype in zip(flat_new_state, nest.flatten(self._state_types)):
          if t.dtype != dtype:
            raise TypeError(
                "The element types for the new state must match the initial "
                "state. Expected %s; got %s." %
                (self._state_types,
                 nest.pack_sequence_as(self._state_types,
                                       [t.dtype for t in flat_new_state])))

        dataset_ops._warn_if_collections("tf.contrib.data.group_by_reducer()")  # pylint: disable=protected-access

        # Serialize any sparse tensors.
        ret = nest.pack_sequence_as(
            ret,
            [t for t in nest.flatten(sparse.serialize_sparse_tensors(ret))])
        return nest.flatten(ret)
Esempio n. 6
0
 def testPackDictOrder(self):
   """Packing orders dicts by key, including OrderedDicts."""
   ordered = collections.OrderedDict([("d", 0), ("b", 0), ("a", 0), ("c", 0)])
   plain = {"d": 0, "b": 0, "a": 0, "c": 0}
   seq = [0, 1, 2, 3]
   ordered_reconstruction = nest.pack_sequence_as(ordered, seq)
   plain_reconstruction = nest.pack_sequence_as(plain, seq)
   self.assertEqual(
       collections.OrderedDict([("d", 3), ("b", 1), ("a", 0), ("c", 2)]),
       ordered_reconstruction)
   self.assertEqual({"d": 3, "b": 1, "a": 0, "c": 2}, plain_reconstruction)
Esempio n. 7
0
    def tf_key_func(*args):
      """A wrapper for Defun that facilitates shape inference."""
      # Pass in shape information from the input_dataset.
      dense_shapes = sparse.as_dense_shapes(input_dataset.output_shapes,
                                            input_dataset.output_classes)
      for arg, shape in zip(args, nest.flatten(dense_shapes)):
        arg.set_shape(shape)

      nested_args = nest.pack_sequence_as(input_dataset.output_types, args)
      nested_args = sparse.deserialize_sparse_tensors(
          nested_args, input_dataset.output_types, input_dataset.output_shapes,
          input_dataset.output_classes)
      # pylint: disable=protected-access
      if dataset_ops._should_unpack_args(nested_args):
        ret = key_func(*nested_args)
      # pylint: enable=protected-access
      else:
        ret = key_func(nested_args)
      ret = ops.convert_to_tensor(ret)
      if ret.dtype != dtypes.int64 or ret.get_shape() != tensor_shape.scalar():
        raise ValueError(
            "`key_func` must return a single tf.int64 tensor. "
            "Got type=%s and shape=%s" % (ret.dtype, ret.get_shape()))
      dataset_ops._warn_if_collections("tf.contrib.data.group_by_reducer()")  # pylint: disable=protected-access
      return ret
Esempio n. 8
0
def normalize_tensors(tensors):
  """Converts a nested structure of tensor-like objects to tensors.

  * `SparseTensor`-like inputs are converted to `SparseTensor`.
  * `TensorArray` inputs are passed through.
  * Everything else is converted to a dense `Tensor`.

  Args:
    tensors: A nested structure of tensor-like, list,
      `SparseTensor`, `SparseTensorValue`, or `TensorArray` objects.

  Returns:
    A nested structure of tensor, `SparseTensor`, or `TensorArray` objects.
  """
  flat_tensors = nest.flatten(tensors)
  prepared = []
  with ops.name_scope("normalize_tensors"):
    for i, t in enumerate(flat_tensors):
      if sparse_tensor_lib.is_sparse(t):
        prepared.append(sparse_tensor_lib.SparseTensor.from_value(t))
      elif ragged_tensor.is_ragged(t):
        prepared.append(
            ragged_tensor.convert_to_tensor_or_ragged_tensor(
                t, name="component_%d" % i))
      elif isinstance(t, tensor_array_ops.TensorArray):
        prepared.append(t)
      else:
        prepared.append(ops.convert_to_tensor(t, name="component_%d" % i))
  return nest.pack_sequence_as(tensors, prepared)
Esempio n. 9
0
 def _check_shape(*elements):
   flatten_tensors = nest.flatten(elements)
   flatten_shapes = nest.flatten(expected_shapes)
   checked_tensors = [with_shape(shape, tensor)
                      for shape, tensor in zip(flatten_shapes,
                                               flatten_tensors)]
   return nest.pack_sequence_as(elements, checked_tensors)
Esempio n. 10
0
  def _next_internal(self):
    """Returns a nested structure of `tf.Tensor`s containing the next element.
    """
    with ops.device(self._device):
      if self._buffer_resource_handle is not None:
        ret = prefetching_ops.function_buffering_resource_get_next(
            function_buffer_resource=self._buffer_resource_handle,
            output_types=self._flat_output_types)
      else:
        # TODO(ashankar): Consider removing this ops.device() contextmanager
        # and instead mimic ops placement in graphs: Operations on resource
        # handles execute on the same device as where the resource is placed.
        # NOTE(mrry): Here we use the "_sync" variant of `iterator_get_next`
        # because in eager mode this code will run synchronously on the calling
        # thread. Therefore we do not need to make a defensive context switch
        # to a background thread, and can achieve a small constant performance
        # boost by invoking the iterator synchronously.
        ret = gen_dataset_ops.iterator_get_next_sync(
            self._resource,
            output_types=self._flat_output_types,
            output_shapes=self._flat_output_shapes)

    return sparse.deserialize_sparse_tensors(
        nest.pack_sequence_as(self._output_types, ret), self._output_types,
        self._output_shapes, self._output_classes)
Esempio n. 11
0
  def get_next(self, name=None):
    """See `tf.data.Iterator.get_next`."""
    self._get_next_call_count += 1
    if self._get_next_call_count > iterator_ops.GET_NEXT_CALL_WARNING_THRESHOLD:
      warnings.warn(iterator_ops.GET_NEXT_CALL_WARNING_MESSAGE)

    flat_result = []
    # TODO(priyag): This will fail if the input size (typically number of
    # batches) is not divisible by number of devices.
    # How do we handle that more gracefully / let the user know?
    for buffer_resource in self._buffering_resources:
      flat_ret = gen_dataset_ops.function_buffering_resource_get_next(
          buffer_resource,
          output_types=data_nest.flatten(sparse.as_dense_types(
              self.output_types, self.output_classes)), name=name)

      ret = sparse.deserialize_sparse_tensors(
          data_nest.pack_sequence_as(self.output_types, flat_ret),
          self.output_types, self.output_shapes, self.output_classes)

      for tensor, shape in zip(
          data_nest.flatten(ret), data_nest.flatten(self.output_shapes)):
        if isinstance(tensor, ops.Tensor):
          tensor.set_shape(shape)
      flat_result.append(ret)

    return nest.pack_sequence_as(self._devices, flat_result)
Esempio n. 12
0
    def generator_map_fn(iterator_id_t):
      """Generates the next element from iterator with ID `iterator_id_t`.

      We map this function across an infinite repetition of the
      `iterator_id_t`, and raise `StopIteration` to terminate the iteration.

      Args:
        iterator_id_t: A `tf.int64` tensor whose value uniquely identifies
          the iterator in `generator_state` from which to generate an element.

      Returns:
        A nested structure of tensors representing an element from the iterator.
      """

      def generator_py_func(iterator_id):
        """A `py_func` that will be called to invoke the iterator."""
        try:
          values = next(generator_state.get_iterator(iterator_id))
        except StopIteration:
          generator_state.iterator_completed(iterator_id)
          raise StopIteration("Iteration finished.")

        # Use the same _convert function from the py_func() implementation to
        # convert the returned values to arrays early, so that we can inspect
        # their values.
        # pylint: disable=protected-access
        ret_arrays = [
            script_ops.FuncRegistry._convert(ret, dtype=dtype.as_numpy_dtype)
            for ret, dtype in zip(nest.flatten_up_to(output_types, values),
                                  flattened_types)
        ]
        # pylint: enable=protected-access

        # Additional type and shape checking to ensure that the components
        # of the generated element match the `output_types` and `output_shapes`
        # arguments.
        for (ret_array, expected_dtype, expected_shape) in zip(
            ret_arrays, flattened_types, flattened_shapes):
          if ret_array.dtype != expected_dtype.as_numpy_dtype:
            raise TypeError(
                "`generator` yielded an element of type %s where an element "
                "of type %s was expected." % (ret_array.dtype,
                                              expected_dtype.as_numpy_dtype))
          if not expected_shape.is_compatible_with(ret_array.shape):
            raise ValueError(
                "`generator` yielded an element of shape %s where an element "
                "of shape %s was expected." % (ret_array.shape, expected_shape))

        return ret_arrays

      flat_values = script_ops.py_func(
          generator_py_func, [iterator_id_t], flattened_types, stateful=True)

      # The `py_func()` op drops the inferred shapes, so we add them back in
      # here.
      if output_shapes is not None:
        for ret_t, shape in zip(flat_values, flattened_shapes):
          ret_t.set_shape(shape)

      return nest.pack_sequence_as(output_types, flat_values)
Esempio n. 13
0
    def tf_map_func(*args):
      """A wrapper for Defun that facilitates shape inference."""
      # Pass in shape information from the input_dataset.
      dense_shapes = sparse.as_dense_shapes(input_dataset.output_shapes,
                                            input_dataset.output_classes)
      for arg, shape in zip(args, nest.flatten(dense_shapes)):
        arg.set_shape(shape)

      nested_args = nest.pack_sequence_as(input_dataset.output_types, args)
      nested_args = sparse.deserialize_sparse_tensors(
          nested_args, input_dataset.output_types, input_dataset.output_shapes,
          input_dataset.output_classes)
      if dataset_ops._should_unpack_args(nested_args):  # pylint: disable=protected-access
        dataset = map_func(*nested_args)
      else:
        dataset = map_func(nested_args)

      if not isinstance(dataset, dataset_ops.Dataset):
        raise TypeError("`map_func` must return a `Dataset` object.")

      self._output_classes = dataset.output_classes
      self._output_types = dataset.output_types
      self._output_shapes = dataset.output_shapes

      return dataset._as_variant_tensor()  # pylint: disable=protected-access
Esempio n. 14
0
  def get_next(self, name=None):
    """Returns a nested structure of `tf.Tensor`s containing the next element.

    Args:
      name: (Optional.) A name for the created operation.

    Returns:
      A nested structure of `tf.Tensor` objects.
    """
    self._get_next_call_count += 1
    if self._get_next_call_count > GET_NEXT_CALL_WARNING_THRESHOLD:
      warnings.warn(GET_NEXT_CALL_WARNING_MESSAGE)

    return sparse.deserialize_sparse_tensors(
        nest.pack_sequence_as(self._output_types,
                              gen_dataset_ops.iterator_get_next(
                                  self._iterator_resource,
                                  output_types=nest.flatten(
                                      sparse.as_dense_types(
                                          self._output_types,
                                          self._output_classes)),
                                  output_shapes=nest.flatten(
                                      sparse.as_dense_shapes(
                                          self._output_shapes,
                                          self._output_classes)),
                                  name=name)), self._output_types,
        self._output_shapes, self._output_classes)
Esempio n. 15
0
  def _make_reduce_func(self, reduce_func, input_dataset):
    """Make wrapping defun for reduce_func."""

    # Iteratively rerun the reduce function until reaching a fixed point on
    # `self._state_shapes`.
    need_to_rerun = True
    while need_to_rerun:

      wrapped_func = dataset_ops.StructuredFunctionWrapper(
          reduce_func,
          self._transformation_name(),
          input_classes=(self._state_classes, input_dataset.output_classes),
          input_shapes=(self._state_shapes, input_dataset.output_shapes),
          input_types=(self._state_types, input_dataset.output_types),
          add_to_graph=False)

      # Extract and validate class information from the returned values.
      for new_state_class, state_class in zip(
          nest.flatten(wrapped_func.output_classes),
          nest.flatten(self._state_classes)):
        if not issubclass(new_state_class, state_class):
          raise TypeError(
              "The element classes for the new state must match the initial "
              "state. Expected %s; got %s." %
              (self._state_classes, wrapped_func.output_classes))

      # Extract and validate type information from the returned values.
      for new_state_type, state_type in zip(
          nest.flatten(wrapped_func.output_types),
          nest.flatten(self._state_types)):
        if new_state_type != state_type:
          raise TypeError(
              "The element types for the new state must match the initial "
              "state. Expected %s; got %s." %
              (self._state_types, wrapped_func.output_types))

      # Extract shape information from the returned values.
      flat_state_shapes = nest.flatten(self._state_shapes)
      flat_new_state_shapes = nest.flatten(wrapped_func.output_shapes)
      weakened_state_shapes = [
          original.most_specific_compatible_shape(new)
          for original, new in zip(flat_state_shapes, flat_new_state_shapes)
      ]

      need_to_rerun = False
      for original_shape, weakened_shape in zip(flat_state_shapes,
                                                weakened_state_shapes):
        if original_shape.ndims is not None and (
            weakened_shape.ndims is None or
            original_shape.as_list() != weakened_shape.as_list()):
          need_to_rerun = True
          break

      if need_to_rerun:
        self._state_shapes = nest.pack_sequence_as(self._state_shapes,
                                                   weakened_state_shapes)

    self._reduce_func = wrapped_func.function
    self._reduce_func.add_to_graph(ops.get_default_graph())
Esempio n. 16
0
 def _merge_output_shapes(original_shapes, expected_shapes):
   flat_original_shapes = nest.flatten(original_shapes)
   flat_new_shapes = nest.flatten_up_to(original_shapes, expected_shapes)
   flat_merged_output_shapes = [
       original_shape.merge_with(new_shape)
       for original_shape, new_shape in zip(flat_original_shapes,
                                            flat_new_shapes)]
   return nest.pack_sequence_as(original_shapes, flat_merged_output_shapes)
Esempio n. 17
0
 def output_shapes(self):
   ret = self._data_inputs[0].output_shapes
   for data_input in self._data_inputs[1:]:
     ret = nest.pack_sequence_as(ret, [
         ts1.most_specific_compatible_shape(ts2) for (ts1, ts2) in zip(
             nest.flatten(ret), nest.flatten(data_input.output_shapes))
     ])
   return ret
Esempio n. 18
0
def convert_legacy_structure(output_types, output_shapes, output_classes):
  """Returns a `Structure` that represents the given legacy structure.

  This method provides a way to convert from the existing `Dataset` and
  `Iterator` structure-related properties to a `Structure` object. A "legacy"
  structure is represented by the `tf.data.Dataset.output_types`,
  `tf.data.Dataset.output_shapes`, and `tf.data.Dataset.output_classes`
  properties.

  TODO(b/110122868): Remove this function once `Structure` is used throughout
  `tf.data`.

  Args:
    output_types: A nested structure of `tf.DType` objects corresponding to
      each component of a structured value.
    output_shapes: A nested structure of `tf.TensorShape` objects
      corresponding to each component a structured value.
    output_classes: A nested structure of Python `type` objects corresponding
      to each component of a structured value.

  Returns:
    A `Structure`.

  Raises:
    TypeError: If a structure cannot be built from the arguments, because one of
      the component classes in `output_classes` is not supported.
  """
  flat_types = nest.flatten(output_types)
  flat_shapes = nest.flatten(output_shapes)
  flat_classes = nest.flatten(output_classes)
  flat_ret = []
  for flat_type, flat_shape, flat_class in zip(flat_types, flat_shapes,
                                               flat_classes):
    if isinstance(flat_class, Structure):
      flat_ret.append(flat_class)
    elif issubclass(flat_class, sparse_tensor_lib.SparseTensor):
      flat_ret.append(SparseTensorStructure(flat_type, flat_shape))
    elif issubclass(flat_class, ops.Tensor):
      flat_ret.append(TensorStructure(flat_type, flat_shape))
    elif issubclass(flat_class, tensor_array_ops.TensorArray):
      # We sneaked the dynamic_size and infer_shape into the legacy shape.
      flat_ret.append(
          TensorArrayStructure(
              flat_type, flat_shape[2:],
              dynamic_size=tensor_shape.dimension_value(flat_shape[0]),
              infer_shape=tensor_shape.dimension_value(flat_shape[1])))
    else:
      # NOTE(mrry): Since legacy structures produced by iterators only
      # comprise Tensors, SparseTensors, and nests, we do not need to
      # support all structure types here.
      raise TypeError(
          "Could not build a structure for output class %r" % (flat_class,))

  ret = nest.pack_sequence_as(output_classes, flat_ret)
  if isinstance(ret, Structure):
    return ret
  else:
    return NestedStructure(ret)
Esempio n. 19
0
 def next(self):
   """Return the next tf.Tensor from the dataset."""
   try:
     ret = gen_dataset_ops.iterator_get_next(
         self._resource,
         output_types=self._flat_output_types,
         output_shapes=self._flat_output_shapes)
     return nest.pack_sequence_as(self._output_types, ret)
   except errors.OutOfRangeError:
     raise StopIteration
Esempio n. 20
0
 def _tf_wrapper(idx):
     flattened_types = nest.flatten(self.tf_dtypes)
     flattened_shapes = nest.flatten(self.tf_shapes)
     flat_values = tf.py_func(func=self._flatten_layer_op,
                              inp=[idx],
                              Tout=flattened_types)
     for ret_t, shape in zip(flat_values, flattened_shapes):
         # the actual returned numpy array shapes are not checked
         ret_t.set_shape(shape)
     return nest.pack_sequence_as(self.tf_dtypes, flat_values)
Esempio n. 21
0
 def make_padded_shapes(shapes, none_filler=None):
   padded = []
   for shape in nest.flatten(shapes):
     shape = tensor_shape.TensorShape(shape)
     shape = [
         none_filler if d.value is None else d
         for d in shape
     ]
     padded.append(shape)
   return nest.pack_sequence_as(shapes, padded)
Esempio n. 22
0
      def tf_scan_func(*args):
        """A wrapper for Defun that facilitates shape inference."""
        # Pass in shape information from the state and input_dataset.
        for arg, shape in zip(
            args,
            flat_state_shapes + nest.flatten(input_dataset.output_shapes)):
          arg.set_shape(shape)

        pivot = len(flat_state_shapes)
        old_state = nest.pack_sequence_as(self._initial_state, args[:pivot])
        input_value = nest.pack_sequence_as(input_dataset.output_types,
                                            args[pivot:])

        ret = scan_func(old_state, input_value)
        if not isinstance(ret, collections.Sequence) or len(ret) != 2:
          raise TypeError("The scan function must return a pair comprising the "
                          "new state and the output value.")
        new_state, output_value = ret

        flat_new_state = [
            ops.convert_to_tensor(t) for t in nest.flatten(new_state)
        ]
        flat_output_value = [
            ops.convert_to_tensor(t) for t in nest.flatten(output_value)
        ]

        # Extract shape information from the returned values.
        flat_new_state_shapes.extend([t.shape for t in flat_new_state])
        self._output_shapes = nest.pack_sequence_as(
            output_value, [t.shape for t in flat_output_value])

        # Extract and validate type information from the returned values.
        for t, dtype in zip(flat_new_state, flat_state_types):
          if t.dtype != dtype:
            raise TypeError(
                "The element types for the new state must match the initial "
                "state. Expected %s; got %s." %
                (self._state_types, nest.pack_sequence_as(
                    self._state_types, [t.dtype for t in flat_new_state])))
        self._output_types = nest.pack_sequence_as(
            output_value, [t.dtype for t in flat_output_value])

        return flat_new_state + flat_output_value
Esempio n. 23
0
  def _from_compatible_tensor_list(self, flat_value):
    flat_ret = []
    i = 0
    for structure in self._flat_nested_structure:
      num_flat_values = len(structure._flat_types)
      sub_value = flat_value[i:i + num_flat_values]
      flat_ret.append(structure._from_compatible_tensor_list(sub_value))
      i += num_flat_values

    return nest.pack_sequence_as(self._nested_structure, flat_ret)
Esempio n. 24
0
 def make_padded_shapes(shapes, none_filler=None):
   padded = []
   for shape in nest.flatten(shapes):
     shape = tensor_shape.TensorShape(shape)
     shape = [
         none_filler if tensor_shape.dimension_value(d) is None else d
         for d in shape
     ]
     padded.append(shape)
   return nest.pack_sequence_as(shapes, padded)
Esempio n. 25
0
 def next(self):
     """Return the next tf.Tensor from the dataset."""
     try:
         ret = gen_dataset_ops.iterator_get_next(
             self._resource,
             output_types=self._flat_output_types,
             output_shapes=self._flat_output_shapes)
         return nest.pack_sequence_as(self._output_types, ret)
     except errors.OutOfRangeError:
         raise StopIteration
Esempio n. 26
0
 def _tf_wrapper(idx):
     flattened_types = nest.flatten(self.tf_dtypes)
     flattened_shapes = nest.flatten(self.tf_shapes)
     flat_values = tf.py_func(func=self._flatten_layer_op,
                              inp=[idx],
                              Tout=flattened_types)
     for ret_t, shape in zip(flat_values, flattened_shapes):
         # the actual returned numpy array shapes are not checked
         ret_t.set_shape(shape)
     return nest.pack_sequence_as(self.tf_dtypes, flat_values)
Esempio n. 27
0
    def _from_compatible_tensor_list(self, flat_value):
        flat_ret = []
        i = 0
        for structure in self._flat_nested_structure:
            num_flat_values = len(structure._flat_types)
            sub_value = flat_value[i:i + num_flat_values]
            flat_ret.append(structure._from_compatible_tensor_list(sub_value))
            i += num_flat_values

        return nest.pack_sequence_as(self._nested_structure, flat_ret)
Esempio n. 28
0
      def tf_scan_func(*args):
        """A wrapper for Defun that facilitates shape inference."""
        # Pass in shape information from the state and input_dataset.
        for arg, shape in zip(
            args,
            flat_state_shapes + nest.flatten(input_dataset.output_shapes)):
          arg.set_shape(shape)

        pivot = len(flat_state_shapes)
        old_state = nest.pack_sequence_as(self._initial_state, args[:pivot])
        input_value = nest.pack_sequence_as(input_dataset.output_types,
                                            args[pivot:])

        ret = scan_func(old_state, input_value)
        if not isinstance(ret, collections.Sequence) or len(ret) != 2:
          raise TypeError("The scan function must return a pair comprising the "
                          "new state and the output value.")
        new_state, output_value = ret

        flat_new_state = [
            ops.convert_to_tensor(t) for t in nest.flatten(new_state)
        ]
        flat_output_value = [
            ops.convert_to_tensor(t) for t in nest.flatten(output_value)
        ]

        # Extract shape information from the returned values.
        flat_new_state_shapes.extend([t.shape for t in flat_new_state])
        self._output_shapes = nest.pack_sequence_as(
            output_value, [t.shape for t in flat_output_value])

        # Extract and validate type information from the returned values.
        for t, dtype in zip(flat_new_state, flat_state_types):
          if t.dtype != dtype:
            raise TypeError(
                "The element types for the new state must match the initial "
                "state. Expected %s; got %s." %
                (self._state_types, nest.pack_sequence_as(
                    self._state_types, [t.dtype for t in flat_new_state])))
        self._output_types = nest.pack_sequence_as(
            output_value, [t.dtype for t in flat_output_value])

        return flat_new_state + flat_output_value
Esempio n. 29
0
  def _from_tensor_list(self, flat_value):
    if len(flat_value) != len(self._flat_types):
      raise ValueError("Expected %d flat values in NestedStructure but got %d."
                       % (len(self._flat_types), len(flat_value)))

    flat_ret = []
    for sub_value, structure in zip(flat_value, self._flat_nested_structure):
      flat_ret.append(structure._from_tensor_list([sub_value]))

    return nest.pack_sequence_as(self._nested_structure, flat_ret)
Esempio n. 30
0
  def __init__(self, dataset, output_types, output_shapes=None):
    """Creates a new dataset with the given output types and shapes.

    The given `dataset` must have a structure that is convertible:
    * `dataset.output_types` must be the same as `output_types` module nesting.
    * Each shape in `dataset.output_shapes` must be compatible with each shape
      in `output_shapes` (if given).

    Note: This helper permits "unsafe casts" for shapes, equivalent to using
    `tf.Tensor.set_shape()` where domain-specific knowledge is available.

    Args:
      dataset: A `Dataset` object.
      output_types: A nested structure of `tf.DType` objects.
      output_shapes: (Optional.) A nested structure of `tf.TensorShape` objects.
        If omitted, the shapes will be inherited from `dataset`.

    Raises:
      ValueError: If either `output_types` or `output_shapes` is not compatible
        with the structure of `dataset`.
    """
    super(_RestructuredDataset, self).__init__()
    self._dataset = dataset

    # Validate that the types are compatible.
    output_types = nest.map_structure(dtypes.as_dtype, output_types)
    flat_original_types = nest.flatten(dataset.output_types)
    flat_new_types = nest.flatten(output_types)
    if flat_original_types != flat_new_types:
      raise ValueError(
          "Dataset with output types %r cannot be restructured to have output "
          "types %r" % (dataset.output_types, output_types))

    self._output_types = output_types

    if output_shapes is None:
      # Inherit shapes from the original `dataset`.
      self._output_shapes = nest.pack_sequence_as(output_types,
                                                  nest.flatten(
                                                      dataset.output_shapes))
    else:
      # Validate that the shapes are compatible.
      nest.assert_same_structure(output_types, output_shapes)
      flat_original_shapes = nest.flatten(dataset.output_shapes)
      flat_new_shapes = nest.flatten_up_to(output_types, output_shapes)

      for original_shape, new_shape in zip(flat_original_shapes,
                                           flat_new_shapes):
        if not original_shape.is_compatible_with(new_shape):
          raise ValueError(
              "Dataset with output shapes %r cannot be restructured to have "
              "incompatible output shapes %r" % (dataset.output_shapes,
                                                 output_shapes))
      self._output_shapes = nest.map_structure_up_to(
          output_types, tensor_shape.as_shape, output_shapes)
Esempio n. 31
0
def normalize_element(element, dtypes=None):
  """Normalizes a nested structure of element components.

  * Components matching `SparseTensorSpec` are converted to `SparseTensor`.
  * Components matching `RaggedTensorSpec` are converted to `RaggedTensor`.
  * Components matching `DatasetSpec` or `TensorArraySpec` are passed through.
  * `CompositeTensor` components are passed through.
  * All other components are converted to `Tensor`.

  Args:
    element: A nested structure of individual components.
    dtypes: (Optional.) A nested structure of `tf.DType` objects corresponding
      to each component of `element`. If specified, it will be used to set the
      exact type of output tensor when converting input components which
      are not tensors themselves (e.g. numpy arrays, native python types, etc.)

  Returns:
    A nested structure of `Tensor`, `Dataset`, `SparseTensor`, `RaggedTensor`,
    or `TensorArray` objects.
  """
  components = nest.flatten(element)
  normalized_components = []
  if dtypes is None:
    flattened_dtypes = [None] * len(components)
  else:
    flattened_dtypes = nest.flatten(dtypes)
  with ops.name_scope("normalize_element"):
    # Imported here to avoid circular dependency.
    from tensorflow.python.data.ops import dataset_ops  # pylint: disable=g-import-not-at-top
    for i, (t, dtype) in enumerate(zip(components, flattened_dtypes)):
      try:
        spec = type_spec_from_value(t, use_fallback=False)
      except TypeError:
        # TypeError indicates it was not possible to compute a `TypeSpec` for
        # the value. As a fallback try converting the value to a tensor.
        normalized_components.append(
            ops.convert_to_tensor(t, name="component_%d" % i, dtype=dtype))
      else:
        if isinstance(spec, sparse_tensor.SparseTensorSpec):
          normalized_components.append(sparse_tensor.SparseTensor.from_value(t))
        elif isinstance(spec, ragged_tensor.RaggedTensorSpec):
          normalized_components.append(
              ragged_tensor.convert_to_tensor_or_ragged_tensor(
                  t, name="component_%d" % i))
        elif isinstance(
            spec, (tensor_array_ops.TensorArraySpec, dataset_ops.DatasetSpec)):
          normalized_components.append(t)
        elif isinstance(spec, NoneTensorSpec):
          normalized_components.append(NoneTensor())
        elif isinstance(t, composite_tensor.CompositeTensor):
          normalized_components.append(t)
        else:
          normalized_components.append(
              ops.convert_to_tensor(t, name="component_%d" % i, dtype=dtype))
  return nest.pack_sequence_as(element, normalized_components)
Esempio n. 32
0
  def __init__(self, dataset, output_types, output_shapes=None):
    """Creates a new dataset with the given output types and shapes.

    The given `dataset` must have a structure that is convertible:
    * `dataset.output_types` must be the same as `output_types` module nesting.
    * Each shape in `dataset.output_shapes` must be compatible with each shape
      in `output_shapes` (if given).

    Note: This helper permits "unsafe casts" for shapes, equivalent to using
    `tf.Tensor.set_shape()` where domain-specific knowledge is available.

    Args:
      dataset: A `Dataset` object.
      output_types: A nested structure of `tf.DType` objects.
      output_shapes: (Optional.) A nested structure of `tf.TensorShape` objects.
        If omitted, the shapes will be inherited from `dataset`.

    Raises:
      ValueError: If either `output_types` or `output_shapes` is not compatible
        with the structure of `dataset`.
    """
    super(_RestructuredDataset, self).__init__()
    self._dataset = dataset

    # Validate that the types are compatible.
    output_types = nest.map_structure(dtypes.as_dtype, output_types)
    flat_original_types = nest.flatten(dataset.output_types)
    flat_new_types = nest.flatten(output_types)
    if flat_original_types != flat_new_types:
      raise ValueError(
          "Dataset with output types %r cannot be restructured to have output "
          "types %r" % (dataset.output_types, output_types))

    self._output_types = output_types

    if output_shapes is None:
      # Inherit shapes from the original `dataset`.
      self._output_shapes = nest.pack_sequence_as(output_types,
                                                  nest.flatten(
                                                      dataset.output_shapes))
    else:
      # Validate that the shapes are compatible.
      nest.assert_same_structure(output_types, output_shapes)
      flat_original_shapes = nest.flatten(dataset.output_shapes)
      flat_new_shapes = nest.flatten_up_to(output_types, output_shapes)

      for original_shape, new_shape in zip(flat_original_shapes,
                                           flat_new_shapes):
        if not original_shape.is_compatible_with(new_shape):
          raise ValueError(
              "Dataset with output shapes %r cannot be restructured to have "
              "incompatible output shapes %r" % (dataset.output_shapes,
                                                 output_shapes))
      self._output_shapes = nest.map_structure_up_to(
          output_types, tensor_shape.as_shape, output_shapes)
Esempio n. 33
0
def convert_legacy_structure(output_types, output_shapes, output_classes):
    """Returns a `Structure` that represents the given legacy structure.

  This method provides a way to convert from the existing `Dataset` and
  `Iterator` structure-related properties to a `Structure` object. A "legacy"
  structure is represented by the `tf.data.Dataset.output_types`,
  `tf.data.Dataset.output_shapes`, and `tf.data.Dataset.output_classes`
  properties.

  TODO(b/110122868): Remove this function once `Structure` is used throughout
  `tf.data`.

  Args:
    output_types: A nested structure of `tf.DType` objects corresponding to
      each component of a structured value.
    output_shapes: A nested structure of `tf.TensorShape` objects
      corresponding to each component a structured value.
    output_classes: A nested structure of Python `type` objects corresponding
      to each component of a structured value.

  Returns:
    A `Structure`.

  Raises:
    TypeError: If a structure cannot be built from the arguments, because one of
      the component classes in `output_classes` is not supported.
  """
    flat_types = nest.flatten(output_types)
    flat_shapes = nest.flatten(output_shapes)
    flat_classes = nest.flatten(output_classes)
    flat_ret = []
    for flat_type, flat_shape, flat_class in zip(flat_types, flat_shapes,
                                                 flat_classes):
        if isinstance(flat_class, type_spec.TypeSpec):
            flat_ret.append(flat_class)
        elif issubclass(flat_class, sparse_tensor.SparseTensor):
            flat_ret.append(SparseTensorStructure(flat_type, flat_shape))
        elif issubclass(flat_class, ops.Tensor):
            flat_ret.append(TensorStructure(flat_type, flat_shape))
        elif issubclass(flat_class, tensor_array_ops.TensorArray):
            # We sneaked the dynamic_size and infer_shape into the legacy shape.
            flat_ret.append(
                TensorArrayStructure(
                    flat_type,
                    flat_shape[2:],
                    dynamic_size=tensor_shape.dimension_value(flat_shape[0]),
                    infer_shape=tensor_shape.dimension_value(flat_shape[1])))
        else:
            # NOTE(mrry): Since legacy structures produced by iterators only
            # comprise Tensors, SparseTensors, and nests, we do not need to
            # support all structure types here.
            raise TypeError("Could not build a structure for output class %r" %
                            (flat_class, ))

    return nest.pack_sequence_as(output_classes, flat_ret)
Esempio n. 34
0
    def __init__(self,
                 selector_input,
                 data_inputs,
                 stop_on_empty_dataset=False):
        self._selector_input = selector_input
        self._data_inputs = list(data_inputs)
        self._stop_on_empty_dataset = stop_on_empty_dataset

        first_output_types = dataset_ops.get_legacy_output_types(
            data_inputs[0])
        first_output_classes = dataset_ops.get_legacy_output_classes(
            data_inputs[0])

        for i, data_input in enumerate(data_inputs[1:]):
            if (dataset_ops.get_legacy_output_types(data_input) !=
                    first_output_types
                    or dataset_ops.get_legacy_output_classes(data_input) !=
                    first_output_classes):
                raise TypeError(
                    "All datasets must have the same type and class.\n"
                    "dataset 0 vs dataset %s types: %s ; %s\n"
                    "classes: %s ; %s" %
                    (i + 1, first_output_types,
                     dataset_ops.get_legacy_output_types(data_input),
                     first_output_classes,
                     dataset_ops.get_legacy_output_classes(data_input)))

        output_shapes = dataset_ops.get_legacy_output_shapes(
            self._data_inputs[0])
        for data_input in self._data_inputs[1:]:
            output_shapes = nest.pack_sequence_as(output_shapes, [
                ts1.most_specific_compatible_shape(ts2) for (ts1, ts2) in zip(
                    nest.flatten(output_shapes),
                    nest.flatten(
                        dataset_ops.get_legacy_output_shapes(data_input)))
            ])
        self._element_spec = structure.convert_legacy_structure(
            first_output_types, output_shapes, first_output_classes)

        compat_kwargs = {}
        if compat.forward_compatible(2021, 5,
                                     14) or self._stop_on_empty_dataset:
            compat_kwargs[
                "stop_on_empty_dataset"] = self._stop_on_empty_dataset

        # pylint: disable=protected-access
        variant_tensor = (
            gen_experimental_dataset_ops.directed_interleave_dataset(
                self._selector_input._variant_tensor, [
                    data_input._variant_tensor
                    for data_input in self._data_inputs
                ], **compat_kwargs, **self._flat_structure))

        super(_DirectedInterleaveDataset, self).__init__(variant_tensor)
Esempio n. 35
0
  def _from_tensor_list(self, flat_value):
    if len(flat_value) != len(self._flat_types):
      raise ValueError("Expected %d flat values in NestedStructure but got %d."
                       % (len(self._flat_types), len(flat_value)))

    flat_ret = []
    for sub_value, structure in zip(flat_value,
                                    nest.flatten(self._nested_structure)):
      flat_ret.append(structure._from_tensor_list([sub_value]))

    return nest.pack_sequence_as(self._nested_structure, flat_ret)
Esempio n. 36
0
 def tpu_pre(loss):
     """Generate the TPU graph."""
     del loss
     values = self.infeed_queue[0].generate_dequeue_op(tpu_device=0)
     unflattened_inputs = data_nest.pack_sequence_as(
         self.feature_structure, values)
     features = unflattened_inputs["features"]
     labels = unflattened_inputs["labels"]
     estimator_spec = model_fn(features, labels,
                               tf.estimator.ModeKeys.TRAIN, mparams)
     return estimator_spec
Esempio n. 37
0
    def _prefetch_fn(handle):
      """Prefetches one element from `input_iterator`."""
      remote_iterator = iterator_ops.Iterator.from_string_handle(
          handle, self._input_iterator.output_types,
          self._input_iterator.output_shapes,
          self._input_iterator.output_classes)
      ret = remote_iterator.get_next()

      # Convert any `SparseTensorValue`s to `SparseTensor`s.
      ret = nest.pack_sequence_as(ret, [
          sparse_tensor_lib.SparseTensor.from_value(t)
          if sparse_tensor_lib.is_sparse(t) else t for t in nest.flatten(ret)
      ])

      # Serialize any sparse tensors and convert result to tensors.
      ret = nest.pack_sequence_as(ret, [
          ops.convert_to_tensor(t)
          for t in nest.flatten(sparse.serialize_sparse_tensors(ret))
      ])
      return nest.flatten(ret)
 def tpu_train_step(loss):
     """Generate the TPU graph."""
     del loss
     values = self.infeed_queue[0].generate_dequeue_op(tpu_device=0)
     unflattened_inputs = data_nest.pack_sequence_as(
         self.feature_structure, values)
     features = unflattened_inputs["features"]
     labels = unflattened_inputs["labels"]
     estimator_spec = model_fn(features, labels,
                               tf.estimator.ModeKeys.TRAIN, params)
     loss, train_op = estimator_spec.loss, estimator_spec.train_op
     with tf.control_dependencies([train_op]):
         return tf.identity(loss)
Esempio n. 39
0
    def tf_init_func(key):
      """A wrapper for Defun that facilitates shape inference."""
      key.set_shape([])
      ret = init_func(key)
      # Convert any `SparseTensorValue`s to `SparseTensor`s and all other
      # values to tensors.
      ret = nest.pack_sequence_as(ret, [
          sparse_tensor.SparseTensor.from_value(t)
          if sparse_tensor.is_sparse(t) else ops.convert_to_tensor(t)
          for t in nest.flatten(ret)
      ])

      self._state_classes = sparse.get_classes(ret)
      self._state_shapes = nest.pack_sequence_as(
          ret, [t.get_shape() for t in nest.flatten(ret)])
      self._state_types = nest.pack_sequence_as(
          ret, [t.dtype for t in nest.flatten(ret)])

      # Serialize any sparse tensors.
      ret = nest.pack_sequence_as(
          ret, [t for t in nest.flatten(sparse.serialize_sparse_tensors(ret))])
      return nest.flatten(ret)
Esempio n. 40
0
 def _next_internal(self):
     """Returns a nested structure of `tf.Tensor`s containing the next element.
 """
     if self._buffer_resource_handle is not None:
         with ops.device(self._device):
             ret = prefetching_ops.function_buffering_resource_get_next(
                 function_buffer_resource=self._buffer_resource_handle,
                 output_types=self._flat_output_types)
         return sparse.deserialize_sparse_tensors(
             nest.pack_sequence_as(self._output_types, ret),
             self._output_types, self._output_shapes, self._output_classes)
     else:
         return super(Iterator, self)._next_internal()
Esempio n. 41
0
 def _next_internal(self):
   """Returns a nested structure of `tf.Tensor`s containing the next element.
   """
   if self._buffer_resource_handle is not None:
     with ops.device(self._device):
       ret = prefetching_ops.function_buffering_resource_get_next(
           function_buffer_resource=self._buffer_resource_handle,
           output_types=self._flat_output_types)
     return sparse.deserialize_sparse_tensors(
         nest.pack_sequence_as(self._output_types, ret), self._output_types,
         self._output_shapes, self._output_classes)
   else:
     return super(Iterator, self)._next_internal()
Esempio n. 42
0
        def grad(*dy):
            """Gradient function for build_rnn."""
            dy = nest.pack_sequence_as(ret, dy)

            def _continue(unused_theta, unused_dy, unused_dstate1,
                          unused_dtheta, unused_dinput, i):
                return _should_continue(i, True)

            dstate1, dtheta, dinput = tf.while_loop(_continue, _cell_grad_fn, [
                theta,
                dy,
                {
                    k: tf.zeros_like(state0[k])
                    for k in state0 if k not in skipped_state
                },
                {
                    k: tf.zeros_like(theta[k])
                    for k in theta if k not in skipped_theta
                },
                {k: tf.zeros_like(inputs[k])
                 for k in inputs},
                tf.zeros([], tf.int32) if reverse else max_length - 1,
            ])[2:5]
            dtheta, dinput = _cell_grad_fn_with_state0(
                state0, theta, dy, dstate1, dtheta, dinput, max_length -
                1 if reverse else tf.zeros([], dtype=tf.int32))[3:5]
            state0_h = tf.reshape(acc_state["h"],
                                  [-1, theta["kernel"].shape[0]])
            state0_atten = tf.reshape(acc_state["attention"], [
                -1, theta["attention_kernel"].shape[0]
            ]) if "attention_kernel" in theta else None
            grad = tf.reshape(dinput["rnn"], [-1, theta["kernel"].shape[1]])
            if reverse:
                state0_h = tf.split(state0_h, [batch_size, -1])[1]
                grad = tf.split(grad, [-1, batch_size])[0]
            else:
                if state0_atten is not None:
                    state0_atten = tf.split(state0_atten, [-1, batch_size])[0]
                state0_h = tf.split(state0_h, [-1, batch_size])[0]
                grad = tf.split(grad, [batch_size, -1])[1]

            if state0_atten is not None:
                dtheta["attention_kernel"] = tf.matmul(
                    tf.transpose(state0_atten), grad)
            dtheta["kernel"] = tf.matmul(tf.transpose(state0_h), grad)

            if "memory_kernel" in orig_theta:
                dtheta["memory_kernel"] = tf.zeros_like(
                    orig_theta["memory_kernel"])
                dtheta["seq_mask"] = tf.zeros_like(orig_theta["seq_mask"])
            return dinput, dtheta
Esempio n. 43
0
        def tf_finalize_func(*args):
            """A wrapper for Defun that facilitates shape inference."""
            for arg, shape in zip(
                    args,
                    nest.flatten(
                        sparse.as_dense_shapes(self._state_shapes,
                                               self._state_classes))):
                arg.set_shape(shape)

            nested_args = nest.pack_sequence_as(self._state_types, args)
            nested_args = sparse.deserialize_sparse_tensors(
                nested_args, self._state_types, self._state_shapes,
                self._state_classes)

            ret = finalize_func(nested_args)

            # Convert any `SparseTensorValue`s to `SparseTensor`s and all other
            # values to tensors.
            ret = nest.pack_sequence_as(ret, [
                sparse_tensor.SparseTensor.from_value(t)
                if sparse_tensor.is_sparse(t) else ops.convert_to_tensor(t)
                for t in nest.flatten(ret)
            ])

            self._output_classes = sparse.get_classes(ret)
            self._output_shapes = nest.pack_sequence_as(
                ret, [t.get_shape() for t in nest.flatten(ret)])
            self._output_types = nest.pack_sequence_as(
                ret, [t.dtype for t in nest.flatten(ret)])

            dataset_ops._warn_if_collections(
                "tf.contrib.data.group_by_reducer()")  # pylint: disable=protected-access

            # Serialize any sparse tensors.
            ret = nest.pack_sequence_as(ret, [
                t for t in nest.flatten(sparse.serialize_sparse_tensors(ret))
            ])
            return nest.flatten(ret)
Esempio n. 44
0
 def next(self):
     """Return the next tf.Tensor from the dataset."""
     try:
         # TODO(ashankar): Consider removing this ops.device() contextmanager
         # and instead mimic ops placement in graphs: Operations on resource
         # handles execute on the same device as where the resource is placed.
         with ops.device("/device:CPU:0"):
             ret = gen_dataset_ops.iterator_get_next(
                 self._resource,
                 output_types=self._flat_output_types,
                 output_shapes=self._flat_output_shapes)
             return nest.pack_sequence_as(self._output_types, ret)
     except errors.OutOfRangeError:
         raise StopIteration
    def _testSaveRestoreUtility(self, start, break_range, stop):
        path = self._iterator_checkpoint_prefix()
        step = 0
        meta_filename = path + "-%d.meta" % step

        input_components = (np.tile(np.array([[1], [2], [3], [4]]), 20),
                            np.tile(np.array([[12], [13], [14], [15]]), 4))
        to_concatenate_components = (np.tile(
            np.array([[5], [6], [7], [8], [9]]),
            20), np.tile(np.array([[16], [17], [18], [19], [20]]), 15))

        with ops.Graph().as_default() as g:
            init_op, get_next = self._build_graph(input_components,
                                                  to_concatenate_components)
            saver = saver_lib.Saver()
            with self.test_session(graph=g) as sess:
                sess.run(init_op)
                for i in range(start, break_range):
                    result = sess.run(get_next)
                    if i < 4:
                        for component, result_component in zip(
                                input_components, result):
                            self.assertAllEqual(component[i], result_component)
                    else:
                        for component, result_component in zip(
                                to_concatenate_components, result):
                            self.assertAllEqual(component[i - 4],
                                                result_component)
                saver.save(sess, path, step)

        with ops.Graph().as_default() as g:
            saver = saver_lib.import_meta_graph(meta_filename)
            with self.test_session(graph=g) as sess:
                get_next = nest.pack_sequence_as(
                    ("a", "b"), ops.get_collection("get_next"))
                saver.restore(sess,
                              saver_lib.latest_checkpoint(self.get_temp_dir()))
                for i in range(break_range, stop):
                    result = sess.run(get_next)
                    if i < 4:
                        for component, result_component in zip(
                                input_components, result):
                            self.assertAllEqual(component[i], result_component)
                    else:
                        for component, result_component in zip(
                                to_concatenate_components, result):
                            self.assertAllEqual(component[i - 4],
                                                result_component)
                with self.assertRaises(errors.OutOfRangeError):
                    sess.run(get_next)
Esempio n. 46
0
  def _from_tensor_list(self, flat_value):
    if len(flat_value) != len(self._flat_types):
      raise ValueError("Expected %d flat values in NestedStructure but got %d."
                       % (len(self._flat_types), len(flat_value)))

    flat_ret = []
    i = 0
    for structure in self._flat_nested_structure:
      num_flat_values = len(structure._flat_types)
      sub_value = flat_value[i:i + num_flat_values]
      flat_ret.append(structure._from_tensor_list(sub_value))
      i += num_flat_values

    return nest.pack_sequence_as(self._nested_structure, flat_ret)
Esempio n. 47
0
 def _next_internal(self):
   """Returns a nested structure of `tf.Tensor`s containing the next element.
   """
   # This runs in sync mode as iterators use an error status to communicate
   # that there is no more data to iterate over.
   # TODO(b/77291417): Fix
   with context.execution_mode(context.SYNC):
     with ops.device(self._device):
       ret = ged_ops.experimental_function_buffering_resource_get_next(
           function_buffer_resource=self._buffering_resource,
           output_types=self._flat_output_types)
     return sparse.deserialize_sparse_tensors(
         nest.pack_sequence_as(self._output_types, ret), self._output_types,
         self._output_shapes, self._output_classes)
Esempio n. 48
0
 def next(self):
   """Return the next tf.Tensor from the dataset."""
   try:
     # TODO(ashankar): Consider removing this ops.device() contextmanager
     # and instead mimic ops placement in graphs: Operations on resource
     # handles execute on the same device as where the resource is placed.
     with ops.device("/device:CPU:0"):
       ret = gen_dataset_ops.iterator_get_next(
           self._resource,
           output_types=self._flat_output_types,
           output_shapes=self._flat_output_shapes)
       return nest.pack_sequence_as(self._output_types, ret)
   except errors.OutOfRangeError:
     raise StopIteration
Esempio n. 49
0
    def __tensors_to_value(self, flat_value, from_tensor_list_fn):
        if len(flat_value) != len(self._flat_tensor_specs):
            raise ValueError(
                "Expected %d flat values in NestedStructure but got %d." %
                (len(self._flat_tensor_specs), len(flat_value)))
        flat_ret = []
        i = 0
        for structure in self._flat_nested_structure:
            num_flat_values = len(structure._flat_tensor_specs)
            sub_value = flat_value[i:i + num_flat_values]
            flat_ret.append(from_tensor_list_fn(structure, sub_value))
            i += num_flat_values

        return nest.pack_sequence_as(self._nested_structure, flat_ret)
Esempio n. 50
0
 def _next_internal(self):
   """Returns a nested structure of `tf.Tensor`s containing the next element.
   """
   # This runs in sync mode as iterators use an error status to communicate
   # that there is no more data to iterate over.
   # TODO(b/77291417): Fix
   with context.execution_mode(context.SYNC):
     with ops.device(self._device):
       ret = gen_dataset_ops.function_buffering_resource_get_next(
           function_buffer_resource=self._buffering_resource,
           output_types=self._flat_output_types)
     return sparse.deserialize_sparse_tensors(
         nest.pack_sequence_as(self._output_types, ret), self._output_types,
         self._output_shapes, self._output_classes)
Esempio n. 51
0
        def tf_init_func(key):
            """A wrapper for Defun that facilitates shape inference."""
            key.set_shape([])
            ret = init_func(key)
            # Convert any `SparseTensorValue`s to `SparseTensor`s and all other
            # values to tensors.
            ret = nest.pack_sequence_as(ret, [
                sparse_tensor.SparseTensor.from_value(t)
                if sparse_tensor.is_sparse(t) else ops.convert_to_tensor(t)
                for t in nest.flatten(ret)
            ])

            self._state_classes = sparse.get_classes(ret)
            self._state_shapes = nest.pack_sequence_as(
                ret, [t.get_shape() for t in nest.flatten(ret)])
            self._state_types = nest.pack_sequence_as(
                ret, [t.dtype for t in nest.flatten(ret)])

            # Serialize any sparse tensors.
            ret = nest.pack_sequence_as(ret, [
                t for t in nest.flatten(sparse.serialize_sparse_tensors(ret))
            ])
            return nest.flatten(ret)
Esempio n. 52
0
    def _from_legacy_structure(output_types, output_shapes, output_classes):
        """Returns a `Structure` that represents the given legacy structure.

    This method provides a way to convert from the existing `Dataset` and
    `Iterator` structure-related properties to a `Structure` object.

    TODO(b/110122868): Remove this method once `Structure` is used throughout
    `tf.data`.

    Args:
      output_types: A nested structure of `tf.DType` objects corresponding to
        each component of a structured value.
      output_shapes: A nested structure of `tf.TensorShape` objects
        corresponding to each component a structured value.
      output_classes: A nested structure of Python `type` objects corresponding
        to each component of a structured value.

    Returns:
      A `Structure`.

    Raises:
      TypeError: If a structure cannot be built the arguments, because one of
        the component classes in `output_classes` is not supported.
    """
        flat_types = nest.flatten(output_types)
        flat_shapes = nest.flatten(output_shapes)
        flat_classes = nest.flatten(output_classes)
        flat_ret = []
        for flat_type, flat_shape, flat_class in zip(flat_types, flat_shapes,
                                                     flat_classes):
            if isinstance(flat_class, Structure):
                flat_ret.append(flat_class)
            elif issubclass(flat_class, sparse_tensor_lib.SparseTensor):
                flat_ret.append(SparseTensorStructure(flat_type, flat_shape))
            elif issubclass(flat_class, ops.Tensor):
                flat_ret.append(TensorStructure(flat_type, flat_shape))
            else:
                # NOTE(mrry): Since legacy structures produced by iterators only
                # comprise Tensors, SparseTensors, and nests, we do not need to
                # support all structure types here.
                raise TypeError(
                    "Could not build a structure for output class %r" %
                    flat_type)

        ret = nest.pack_sequence_as(output_classes, flat_ret)
        if isinstance(ret, Structure):
            return ret
        else:
            return NestedStructure(ret)
Esempio n. 53
0
def get_single_element(dataset):
  """Returns the single element in `dataset` as a nested structure of tensors.

  This function enables you to use a @{tf.data.Dataset} in a stateless
  "tensor-in tensor-out" expression, without creating a @{tf.data.Iterator}.
  This can be useful when your preprocessing transformations are expressed
  as a `Dataset`, and you want to use the transformation at serving time.
  For example:

  ```python
  input_batch = tf.placeholder(tf.string, shape=[BATCH_SIZE])

  def preprocessing_fn(input_str):
    # ...
    return image, label

  dataset = (tf.data.Dataset.from_tensor_slices(input_batch)
             .map(preprocessing_fn, num_parallel_calls=BATCH_SIZE)
             .batch(BATCH_SIZE))

  image_batch, label_batch = tf.contrib.data.get_single_element(dataset)
  ```

  Args:
    dataset: A @{tf.data.Dataset} object containing a single element.

  Returns:
    A nested structure of @{tf.Tensor} objects, corresponding to the single
    element of `dataset`.

  Raises:
    TypeError: if `dataset` is not a `tf.data.Dataset` object.
    InvalidArgumentError (at runtime): if `dataset` does not contain exactly
      one element.
  """
  if not isinstance(dataset, dataset_ops.Dataset):
    raise TypeError("`dataset` must be a `tf.data.Dataset` object.")

  nested_ret = nest.pack_sequence_as(
      dataset.output_types, gen_dataset_ops.dataset_to_single_element(
          dataset._as_variant_tensor(),  # pylint: disable=protected-access
          output_types=nest.flatten(sparse.as_dense_types(
              dataset.output_types, dataset.output_classes)),
          output_shapes=nest.flatten(sparse.as_dense_shapes(
              dataset.output_shapes, dataset.output_classes))))
  return sparse.deserialize_sparse_tensors(
      nested_ret, dataset.output_types, dataset.output_shapes,
      dataset.output_classes)
Esempio n. 54
0
def normalize_element(element):
    """Normalizes a nested structure of element components.

  * Components matching `SparseTensorSpec` are converted to `SparseTensor`.
  * Components matching `RaggedTensorSpec` are converted to `RaggedTensor`.
  * Components matching `DatasetSpec` or `TensorArraySpec` are passed through.
  * `CompositeTensor` components are passed through.
  * All other components are converted to `Tensor`.

  Args:
    element: A nested structure of individual components.

  Returns:
    A nested structure of `Tensor`, `Dataset`, `SparseTensor`, `RaggedTensor`,
    or `TensorArray` objects.
  """
    components = nest.flatten(element)
    normalized_components = []
    with ops.name_scope("normalize_element"):
        # Imported here to avoid circular dependency.
        from tensorflow.python.data.ops import dataset_ops  # pylint: disable=g-import-not-at-top
        for i, t in enumerate(components):
            try:
                spec = type_spec_from_value(t, use_fallback=False)
            except TypeError:
                # TypeError indicates it was not possible to compute a `TypeSpec` for
                # the value. As a fallback try converting the value to a tensor.
                normalized_components.append(
                    ops.convert_to_tensor(t, name="component_%d" % i))
            else:
                if isinstance(spec, sparse_tensor.SparseTensorSpec):
                    normalized_components.append(
                        sparse_tensor.SparseTensor.from_value(t))
                elif isinstance(spec, ragged_tensor.RaggedTensorSpec):
                    normalized_components.append(
                        ragged_tensor.convert_to_tensor_or_ragged_tensor(
                            t, name="component_%d" % i))
                elif isinstance(spec, (tensor_array_ops.TensorArraySpec,
                                       dataset_ops.DatasetSpec)):
                    normalized_components.append(t)
                elif isinstance(spec, NoneTensorSpec):
                    normalized_components.append(NoneTensor())
                elif isinstance(t, composite_tensor.CompositeTensor):
                    normalized_components.append(t)
                else:
                    normalized_components.append(
                        ops.convert_to_tensor(t, name="component_%d" % i))
    return nest.pack_sequence_as(element, normalized_components)
Esempio n. 55
0
def get_classes(tensors):
  """Gets classes for a structure of tensors.

  Args:
    tensors: the tensor structure to get classes for.

  Returns:
    a structure matching the nested structure of `tensors`, containing
    `tf.SparseTensor` at positions where `tensors` contains a sparse tensor and
    `tf.Tensor` otherwise
  """
  return nest.pack_sequence_as(tensors, [
      sparse_tensor.SparseTensor
      if isinstance(tensor, sparse_tensor.SparseTensor) else ops.Tensor
      for tensor in nest.flatten(tensors)
  ])
Esempio n. 56
0
    def tpu_eval_step():
      """Generate the TPU graph."""
      values = self.infeed_queue[0].generate_dequeue_op(tpu_device=0)
      unflattened_inputs = data_nest.pack_sequence_as(self.feature_structure,
                                                      values)
      features = unflattened_inputs["features"]
      estimator_spec = model_fn(features, None, tf.estimator.ModeKeys.PREDICT,
                                params)
      for k, v in six.iteritems(estimator_spec.predictions):
        self.outfeed_names.append(k)
        self.outfeed_tensors.append(v)

      with tf.device(utils.device_for_tpu_core(self._get_host(0))):
        outfeed_enqueue_ops = tpu.outfeed_enqueue_tuple(self.outfeed_tensors)
      with tf.control_dependencies([outfeed_enqueue_ops]):
        return tf.no_op()
Esempio n. 57
0
    def get_next(self, name=None):
        """Returns a nested structure of `tf.Tensor`s containing the next element.

    Args:
      name: (Optional.) A name for the created operation.

    Returns:
      A nested structure of `tf.Tensor` objects.
    """
        return nest.pack_sequence_as(
            self._output_types,
            gen_dataset_ops.iterator_get_next(
                self._iterator_resource,
                output_types=nest.flatten(self._output_types),
                output_shapes=nest.flatten(self._output_shapes),
                name=name))
Esempio n. 58
0
def serialize_sparse_tensors(tensors):
  """Serializes sparse tensors.

  Args:
    tensors: a tensor structure to serialize.

  Returns:
    `tensors` with any sparse tensors replaced by the their serialized version.
  """

  ret = nest.pack_sequence_as(tensors, [
      sparse_ops.serialize_sparse(tensor)
      if isinstance(tensor, sparse_tensor.SparseTensor) else tensor
      for tensor in nest.flatten(tensors)
  ])
  return ret
Esempio n. 59
0
def get_sparse_types(tensors):
  """Gets sparse types for a structure of tensors.

  Args:
    tensors: the tensor structure to get sparse types for.

  Returns:
    a structure matching the nested structure of `tensors`, containing
    `SparseType` at positions where `tensors` contains a sparse tensor and
    `None` otherwise
  """
  return nest.pack_sequence_as(tensors, [
      SparseType(tensor.dtype)
      if isinstance(tensor, sparse_tensor.SparseTensor) else None
      for tensor in nest.flatten(tensors)
  ])
Esempio n. 60
0
def unwrap_sparse_types(types):
  """Unwraps sparse tensor types as `dtypes.string`.

  Args:
    types: a structure of types to unwrap.

  Returns:
    a structure matching the nested structure of `types`, containing
    `dtypes.string` at positions where `types` contains a sparse tensor and
    matching contents of `types` otherwise
  """
  ret = nest.pack_sequence_as(types, [
      dtypes.string if isinstance(ty, SparseType) else ty
      for ty in nest.flatten(types)
  ])
  return ret