def _prepare_inputs_for_rnn(sequence_features, context_features,
                            sequence_feature_columns, num_unroll):
  """Prepares features batched by the SQSS for input to a state-saving RNN.

  Args:
    sequence_features: A dict of sequence feature name to `Tensor` or
      `SparseTensor`, with `Tensor`s of shape `[batch_size, num_unroll, ...]`
      or `SparseTensors` of dense shape `[batch_size, num_unroll, d]`.
    context_features: A dict of context feature name to `Tensor`, with
      tensors of shape `[batch_size, 1, ...]` and type float32.
    sequence_feature_columns: An iterable containing all the feature columns
      describing sequence features. All items in the set should be instances
      of classes derived from `FeatureColumn`.
    num_unroll: Python integer, how many time steps to unroll at a time.
      The input sequences of length `k` are then split into `k / num_unroll`
      many segments.

  Returns:
    features_by_time: A list of length `num_unroll` with `Tensor` entries of
      shape `[batch_size, sum(sequence_features dimensions) +
      sum(context_features dimensions)]` of type float32.
      Context features are copied into each time step.
  """

  def _tile(feature):
    return array_ops.squeeze(
        array_ops.tile(array_ops.expand_dims(feature, 1), [1, num_unroll, 1]),
        axis=2)
  for feature in sequence_features.values():
    if isinstance(feature, sparse_tensor.SparseTensor):
      # Explicitly set dense_shape's shape to 3 ([batch_size, num_unroll, d])
      # since it can't be statically inferred.
      feature.dense_shape.set_shape([3])
  sequence_features = layers.sequence_input_from_feature_columns(
      columns_to_tensors=sequence_features,
      feature_columns=sequence_feature_columns,
      weight_collections=None,
      scope=None)
  # Explicitly set shape along dimension 1 to num_unroll for the unstack op.
  sequence_features.set_shape([None, num_unroll, None])

  if not context_features:
    return array_ops.unstack(sequence_features, axis=1)
  # TODO(jtbates): Call layers.input_from_feature_columns for context features.
  context_features = [
      _tile(context_features[k]) for k in sorted(context_features)
  ]
  return array_ops.unstack(
      array_ops.concat(
          [sequence_features, array_ops.stack(context_features, 2)], axis=2),
      axis=1)
Example #2
0
def _prepare_inputs_for_rnn(sequence_features, context_features,
                            sequence_feature_columns, num_unroll):
    """Prepares features batched by the SQSS for input to a state-saving RNN.

  Args:
    sequence_features: A dict of sequence feature name to `Tensor` or
      `SparseTensor`, with `Tensor`s of shape `[batch_size, num_unroll, ...]`
      or `SparseTensors` of dense shape `[batch_size, num_unroll, d]`.
    context_features: A dict of context feature name to `Tensor`, with
      tensors of shape `[batch_size, 1, ...]` and type float32.
    sequence_feature_columns: An iterable containing all the feature columns
      describing sequence features. All items in the set should be instances
      of classes derived from `FeatureColumn`.
    num_unroll: Python integer, how many time steps to unroll at a time.
      The input sequences of length `k` are then split into `k / num_unroll`
      many segments.

  Returns:
    features_by_time: A list of length `num_unroll` with `Tensor` entries of
      shape `[batch_size, sum(sequence_features dimensions) +
      sum(context_features dimensions)]` of type float32.
      Context features are copied into each time step.
  """
    def _tile(feature):
        return array_ops.squeeze(array_ops.tile(
            array_ops.expand_dims(feature, 1), [1, num_unroll, 1]),
                                 axis=2)

    for feature in sequence_features.values():
        if isinstance(feature, sparse_tensor.SparseTensor):
            # Explicitly set dense_shape's shape to 3 ([batch_size, num_unroll, d])
            # since it can't be statically inferred.
            feature.dense_shape.set_shape([3])
    sequence_features = layers.sequence_input_from_feature_columns(
        columns_to_tensors=sequence_features,
        feature_columns=sequence_feature_columns,
        weight_collections=None,
        scope=None)
    # Explicitly set shape along dimension 1 to num_unroll for the unstack op.
    sequence_features.set_shape([None, num_unroll, None])

    if not context_features:
        return array_ops.unstack(sequence_features, axis=1)
    # TODO(jtbates): Call layers.input_from_feature_columns for context features.
    context_features = [
        _tile(context_features[k]) for k in sorted(context_features)
    ]
    return array_ops.unstack(array_ops.concat(
        [sequence_features,
         array_ops.stack(context_features, 2)], axis=2),
                             axis=1)
Example #3
0
def build_sequence_input(features,
                         sequence_feature_columns,
                         context_feature_columns,
                         weight_collections=None,
                         scope=None):
    """Combine sequence and context features into input for an RNN.

  Args:
    features: A `dict` containing the input and (optionally) sequence length
      information and initial state.
    sequence_feature_columns: An iterable containing all the feature columns
      describing sequence features. All items in the set should be instances
      of classes derived from `FeatureColumn`.
    context_feature_columns: An iterable containing all the feature columns
      describing context features i.e. features that apply across all time
      steps. All items in the set should be instances of classes derived from
      `FeatureColumn`.
    weight_collections: List of graph collections to which weights are added.
    scope: Optional scope, passed through to parsing ops.
  Returns:
    A `Tensor` of dtype `float32` and shape `[batch_size, padded_length, ?]`.
    This will be used as input to an RNN.
  """
    features = features.copy()
    features.update(
        layers.transform_features(
            features,
            list(sequence_feature_columns) +
            list(context_feature_columns or [])))
    sequence_input = layers.sequence_input_from_feature_columns(
        columns_to_tensors=features,
        feature_columns=sequence_feature_columns,
        weight_collections=weight_collections,
        scope=scope)
    if context_feature_columns is not None:
        context_input = layers.input_from_feature_columns(
            columns_to_tensors=features,
            feature_columns=context_feature_columns,
            weight_collections=weight_collections,
            scope=scope)
        sequence_input = _concatenate_context_input(sequence_input,
                                                    context_input)
    return sequence_input
  def _get_model_input(self, features, weight_collections=None, scope=None):
    # TODO(jamieas): add option to use context to construct initial state rather
    # than appending it to sequence input.
    initial_state = features.get(self._initial_state_key)

    sequence_input = layers.sequence_input_from_feature_columns(
        columns_to_tensors=features,
        feature_columns=self._sequence_feature_columns,
        weight_collections=weight_collections,
        scope=scope)

    if self._context_feature_columns is not None:
      context_input = layers.input_from_feature_columns(
          columns_to_tensors=features,
          feature_columns=self._context_feature_columns,
          weight_collections=weight_collections,
          scope=scope)

      sequence_input = _concatenate_context_input(sequence_input, context_input)

    return initial_state, sequence_input
  def _get_model_input(self, features, weight_collections=None, scope=None):
    # TODO(jamieas): add option to use context to construct initial state rather
    # than appending it to sequence input.
    initial_state = features.get(self._initial_state_key)

    sequence_input = layers.sequence_input_from_feature_columns(
        columns_to_tensors=features,
        feature_columns=self._sequence_feature_columns,
        weight_collections=weight_collections,
        scope=scope)

    if self._context_feature_columns is not None:
      context_input = layers.input_from_feature_columns(
          columns_to_tensors=features,
          feature_columns=self._context_feature_columns,
          weight_collections=weight_collections,
          scope=scope)

      sequence_input = _concatenate_context_input(sequence_input, context_input)

    return initial_state, sequence_input
def build_sequence_input(features,
                         sequence_feature_columns,
                         context_feature_columns,
                         weight_collections=None,
                         scope=None):
  """Combine sequence and context features into input for an RNN.

  Args:
    features: A `dict` containing the input and (optionally) sequence length
      information and initial state.
    sequence_feature_columns: An iterable containing all the feature columns
      describing sequence features. All items in the set should be instances
      of classes derived from `FeatureColumn`.
    context_feature_columns: An iterable containing all the feature columns
      describing context features i.e. features that apply across all time
      steps. All items in the set should be instances of classes derived from
      `FeatureColumn`.
    weight_collections: List of graph collections to which weights are added.
    scope: Optional scope, passed through to parsing ops.
  Returns:
    A `Tensor` of dtype `float32` and shape `[batch_size, padded_length, ?]`.
    This will be used as input to an RNN.
  """
  features = features.copy()
  features.update(layers.transform_features(
      features,
      list(sequence_feature_columns) + list(context_feature_columns or [])))
  sequence_input = layers.sequence_input_from_feature_columns(
      columns_to_tensors=features,
      feature_columns=sequence_feature_columns,
      weight_collections=weight_collections,
      scope=scope)
  if context_feature_columns is not None:
    context_input = layers.input_from_feature_columns(
        columns_to_tensors=features,
        feature_columns=context_feature_columns,
        weight_collections=weight_collections,
        scope=scope)
    sequence_input = _concatenate_context_input(sequence_input, context_input)
  return sequence_input