Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/keras/src/feature_column/sequence_feature_column.py: 36%
45 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
1# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""This API defines FeatureColumn for sequential input.
17NOTE: This API is a work in progress and will likely be changing frequently.
18"""
20from __future__ import absolute_import
21from __future__ import division
22from __future__ import print_function
24import tensorflow.compat.v2 as tf
26from keras.src import backend
27from keras.src.feature_column import base_feature_layer as kfc
29# isort: off
30from tensorflow.python.util.tf_export import keras_export
33@keras_export("keras.experimental.SequenceFeatures")
34class SequenceFeatures(kfc._BaseFeaturesLayer):
35 """A layer for sequence input.
37 All `feature_columns` must be sequence dense columns with the same
38 `sequence_length`. The output of this method can be fed into sequence
39 networks, such as RNN.
41 The output of this method is a 3D `Tensor` of shape `[batch_size, T, D]`.
42 `T` is the maximum sequence length for this batch, which could differ from
43 batch to batch.
45 If multiple `feature_columns` are given with `Di` `num_elements` each, their
46 outputs are concatenated. So, the final `Tensor` has shape
47 `[batch_size, T, D0 + D1 + ... + Dn]`.
49 Example:
51 ```python
53 import tensorflow as tf
55 # Behavior of some cells or feature columns may depend on whether we are in
56 # training or inference mode, e.g. applying dropout.
57 training = True
58 rating = tf.feature_column.sequence_numeric_column('rating')
59 watches = tf.feature_column.sequence_categorical_column_with_identity(
60 'watches', num_buckets=1000)
61 watches_embedding = tf.feature_column.embedding_column(watches,
62 dimension=10)
63 columns = [rating, watches_embedding]
65 features = {
66 'rating': tf.sparse.from_dense([[1.0,1.1, 0, 0, 0],
67 [2.0,2.1,2.2, 2.3, 2.5]]),
68 'watches': tf.sparse.from_dense([[2, 85, 0, 0, 0],[33,78, 2, 73, 1]])
69 }
71 sequence_input_layer = tf.keras.experimental.SequenceFeatures(columns)
72 sequence_input, sequence_length = sequence_input_layer(
73 features, training=training)
74 sequence_length_mask = tf.sequence_mask(sequence_length)
75 hidden_size = 32
76 rnn_cell = tf.keras.layers.SimpleRNNCell(hidden_size)
77 rnn_layer = tf.keras.layers.RNN(rnn_cell)
78 outputs, state = rnn_layer(sequence_input, mask=sequence_length_mask)
79 ```
80 """
82 def __init__(self, feature_columns, trainable=True, name=None, **kwargs):
83 """ "Constructs a SequenceFeatures layer.
85 Args:
86 feature_columns: An iterable of dense sequence columns. Valid columns
87 are
88 - `embedding_column` that wraps a
89 `sequence_categorical_column_with_*`
90 - `sequence_numeric_column`.
91 trainable: Boolean, whether the layer's variables will be updated via
92 gradient descent during training.
93 name: Name to give to the SequenceFeatures.
94 **kwargs: Keyword arguments to construct a layer.
96 Raises:
97 ValueError: If any of the `feature_columns` is not a
98 `SequenceDenseColumn`.
99 """
100 super().__init__(
101 feature_columns=feature_columns,
102 trainable=trainable,
103 name=name,
104 expected_column_type=tf.__internal__.feature_column.SequenceDenseColumn, # noqa: E501
105 **kwargs
106 )
108 @property
109 def _is_feature_layer(self):
110 return True
112 def _target_shape(self, input_shape, total_elements):
113 return (input_shape[0], input_shape[1], total_elements)
115 def call(self, features, training=None):
116 """Returns sequence input corresponding to the `feature_columns`.
118 Args:
119 features: A dict mapping keys to tensors.
120 training: Python boolean or None, indicating whether to the layer is
121 being run in training mode. This argument is passed to the call
122 method of any `FeatureColumn` that takes a `training` argument. For
123 example, if a `FeatureColumn` performed dropout, the column could
124 expose a `training` argument to control whether the dropout should
125 be applied. If `None`, defaults to
126 `tf.keras.backend.learning_phase()`.
129 Returns:
130 An `(input_layer, sequence_length)` tuple where:
131 - input_layer: A float `Tensor` of shape `[batch_size, T, D]`.
132 `T` is the maximum sequence length for this batch, which could
133 differ from batch to batch. `D` is the sum of `num_elements` for
134 all `feature_columns`.
135 - sequence_length: An int `Tensor` of shape `[batch_size]`. The
136 sequence length for each example.
138 Raises:
139 ValueError: If features are not a dictionary.
140 """
141 if not isinstance(features, dict):
142 raise ValueError(
143 "We expected a dictionary here. Instead we got: ", features
144 )
145 if training is None:
146 training = backend.learning_phase()
147 transformation_cache = (
148 tf.__internal__.feature_column.FeatureTransformationCache(features)
149 )
150 output_tensors = []
151 sequence_lengths = []
153 for column in self._feature_columns:
154 with backend.name_scope(column.name):
155 try:
156 (
157 dense_tensor,
158 sequence_length,
159 ) = column.get_sequence_dense_tensor(
160 transformation_cache,
161 self._state_manager,
162 training=training,
163 )
164 except TypeError:
165 (
166 dense_tensor,
167 sequence_length,
168 ) = column.get_sequence_dense_tensor(
169 transformation_cache, self._state_manager
170 )
171 # Flattens the final dimension to produce a 3D Tensor.
172 output_tensors.append(
173 self._process_dense_tensor(column, dense_tensor)
174 )
175 sequence_lengths.append(sequence_length)
177 # Check and process sequence lengths.
178 kfc._verify_static_batch_size_equality(
179 sequence_lengths, self._feature_columns
180 )
181 sequence_length = _assert_all_equal_and_return(sequence_lengths)
183 return self._verify_and_concat_tensors(output_tensors), sequence_length
186def _assert_all_equal_and_return(tensors, name=None):
187 """Asserts that all tensors are equal and returns the first one."""
188 with backend.name_scope(name or "assert_all_equal"):
189 if len(tensors) == 1:
190 return tensors[0]
191 assert_equal_ops = []
192 for t in tensors[1:]:
193 assert_equal_ops.append(tf.compat.v1.assert_equal(tensors[0], t))
194 with tf.control_dependencies(assert_equal_ops):
195 return tf.identity(tensors[0])