Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/keras/engine/input_layer.py: 17%
129 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 2015 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# pylint: disable=protected-access
16"""Input layer code (`Input` and `InputLayer`)."""
18from tensorflow.python.distribute import distribute_lib
19from tensorflow.python.framework import ops
20from tensorflow.python.framework import tensor_shape
21from tensorflow.python.framework import tensor_spec
22from tensorflow.python.keras import backend
23from tensorflow.python.keras.distribute import distributed_training_utils
24from tensorflow.python.keras.engine import base_layer
25from tensorflow.python.keras.engine import keras_tensor
26from tensorflow.python.keras.engine import node as node_module
27from tensorflow.python.keras.saving.saved_model import layer_serialization
28from tensorflow.python.keras.utils import tf_utils
29from tensorflow.python.util.tf_export import keras_export
32def _assert_other_arg_none(arg_name, arg):
33 if arg is not None:
34 raise ValueError('When `type_spec` is not None, all other args '
35 'except `name` must be None, '
36 'but %s is not None.' % arg_name)
39@keras_export('keras.layers.InputLayer')
40class InputLayer(base_layer.Layer):
41 """Layer to be used as an entry point into a Network (a graph of layers).
43 It can either wrap an existing tensor (pass an `input_tensor` argument)
44 or create a placeholder tensor (pass arguments `input_shape`, and
45 optionally, `dtype`).
47 It is generally recommend to use the functional layer API via `Input`,
48 (which creates an `InputLayer`) without directly using `InputLayer`.
50 When using InputLayer with Keras Sequential model, it can be skipped by
51 moving the input_shape parameter to the first layer after the InputLayer.
53 This class can create placeholders for tf.Tensors, tf.SparseTensors, and
54 tf.RaggedTensors by choosing 'sparse=True' or 'ragged=True'. Note that
55 'sparse' and 'ragged' can't be configured to True at same time.
56 Usage:
58 ```python
59 # With explicit InputLayer.
60 model = tf.keras.Sequential([
61 tf.keras.layers.InputLayer(input_shape=(4,)),
62 tf.keras.layers.Dense(8)])
63 model.compile(tf.optimizers.RMSprop(0.001), loss='mse')
64 model.fit(np.zeros((10, 4)),
65 np.ones((10, 8)))
67 # Without InputLayer and let the first layer to have the input_shape.
68 # Keras will add a input for the model behind the scene.
69 model = tf.keras.Sequential([
70 tf.keras.layers.Dense(8, input_shape=(4,))])
71 model.compile(tf.optimizers.RMSprop(0.001), loss='mse')
72 model.fit(np.zeros((10, 4)),
73 np.ones((10, 8)))
74 ```
76 Args:
77 input_shape: Shape tuple (not including the batch axis), or `TensorShape`
78 instance (not including the batch axis).
79 batch_size: Optional input batch size (integer or None).
80 dtype: Optional datatype of the input. When not provided, the Keras
81 default float type will be used.
82 input_tensor: Optional tensor to use as layer input. If set, the layer
83 will use the `tf.TypeSpec` of this tensor rather
84 than creating a new placeholder tensor.
85 sparse: Boolean, whether the placeholder created is meant to be sparse.
86 Default to False.
87 ragged: Boolean, whether the placeholder created is meant to be ragged.
88 In this case, values of 'None' in the 'shape' argument represent
89 ragged dimensions. For more information about RaggedTensors, see
90 [this guide](https://www.tensorflow.org/guide/ragged_tensors).
91 Default to False.
92 type_spec: A `tf.TypeSpec` object to create Input from. This `tf.TypeSpec`
93 represents the entire batch. When provided, all other args except
94 name must be None.
95 name: Optional name of the layer (string).
96 """
98 def __init__(self,
99 input_shape=None,
100 batch_size=None,
101 dtype=None,
102 input_tensor=None,
103 sparse=None,
104 name=None,
105 ragged=None,
106 type_spec=None,
107 **kwargs):
108 self._init_input_shape = input_shape
109 self._init_batch_size = batch_size
110 self._init_dtype = dtype
111 self._init_sparse = sparse
112 self._init_ragged = ragged
113 self._init_type_spec = type_spec
115 strategy = distribute_lib.get_strategy()
116 if strategy and batch_size is not None and \
117 distributed_training_utils.global_batch_size_supported(strategy):
118 if batch_size % strategy.num_replicas_in_sync != 0:
119 raise ValueError('The `batch_size` argument ({}) must be divisible by '
120 'the number of replicas ({})'.format(
121 batch_size, strategy.num_replicas_in_sync))
122 batch_size = batch_size // strategy.num_replicas_in_sync
124 if 'batch_input_shape' in kwargs:
125 batch_input_shape = kwargs.pop('batch_input_shape')
126 if input_shape and batch_input_shape:
127 raise ValueError('Only provide the input_shape OR '
128 'batch_input_shape argument to '
129 'InputLayer, not both at the same time.')
130 # Set the input shape and batch size from the batch_input_shape.
131 # Note that batch_input_shape can be None (unknown rank) or [] (scalar),
132 # in which case the batch size must be None.
133 if batch_input_shape:
134 batch_size = batch_input_shape[0]
135 input_shape = batch_input_shape[1:]
136 if kwargs:
137 raise ValueError('Unrecognized keyword arguments:', kwargs.keys())
139 if sparse and ragged:
140 raise ValueError(
141 'Cannot set both sparse and ragged to True in a Keras input.')
143 if not name:
144 prefix = 'input'
145 name = prefix + '_' + str(backend.get_uid(prefix))
147 if not dtype:
148 if input_tensor is None:
149 dtype = backend.floatx()
150 else:
151 dtype = backend.dtype(input_tensor)
152 elif input_tensor is not None and input_tensor.dtype != dtype:
153 raise ValueError('`input_tensor.dtype` differs from `dtype`: %s vs. %s' %
154 (input_tensor.dtype, dtype))
155 super(InputLayer, self).__init__(dtype=dtype, name=name)
156 self.built = True
157 self.sparse = True if sparse else False
158 self.ragged = True if ragged else False
159 self.batch_size = batch_size
160 self.supports_masking = True
162 if isinstance(input_shape, tensor_shape.TensorShape):
163 input_shape = tuple(input_shape.as_list())
164 elif isinstance(input_shape, int):
165 input_shape = (input_shape,)
167 if type_spec is not None:
168 args_that_must_be_none = [
169 ('(input_)shape', self._init_input_shape),
170 ('batch_size', self._init_batch_size),
171 ('dtype', self._init_dtype),
172 ('input_tensor', input_tensor),
173 ('sparse', self._init_sparse),
174 ('ragged', self._init_ragged),
175 ]
176 for arg_name, arg in args_that_must_be_none:
177 _assert_other_arg_none(arg_name, arg)
178 if not ops.executing_eagerly_outside_functions():
179 raise ValueError('Creating Keras inputs from a type_spec is only '
180 'supported when eager execution is enabled.')
181 input_tensor = keras_tensor.keras_tensor_from_type_spec(type_spec)
182 if isinstance(input_tensor, keras_tensor.SparseKerasTensor):
183 self.sparse = True
184 if isinstance(input_tensor, keras_tensor.RaggedKerasTensor):
185 self.ragged = True
186 self.is_placeholder = True
187 try:
188 self._batch_input_shape = tuple(input_tensor.shape.as_list())
189 except ValueError:
190 # If the shape cannot be represented as a tuple (e.g. unknown rank)
191 self._batch_input_shape = None
192 elif input_tensor is None:
193 if input_shape is not None:
194 batch_input_shape = (batch_size,) + tuple(input_shape)
195 else:
196 batch_input_shape = None
197 graph = backend.get_graph()
198 with graph.as_default():
199 input_tensor = backend.placeholder(
200 shape=batch_input_shape,
201 dtype=dtype,
202 name=self.name,
203 sparse=sparse,
204 ragged=ragged)
206 self.is_placeholder = True
207 self._batch_input_shape = batch_input_shape
208 else:
209 if ops.executing_eagerly_outside_functions():
210 if not isinstance(input_tensor, keras_tensor.KerasTensor):
211 input_tensor = keras_tensor.keras_tensor_from_tensor(input_tensor)
212 else:
213 if not tf_utils.is_symbolic_tensor(input_tensor):
214 raise ValueError('You should not pass an EagerTensor to `Input`. '
215 'For example, instead of creating an '
216 'InputLayer, you should instantiate your model and '
217 'directly call it on your input.')
218 self.is_placeholder = False
219 try:
220 self._batch_input_shape = tuple(input_tensor.shape.as_list())
221 except ValueError:
222 # If the shape cannot be represented as a tuple (e.g. unknown rank)
223 self._batch_input_shape = None
224 # Create an input node.
225 input_tensor._keras_mask = None
226 node_module.Node(layer=self, outputs=input_tensor)
228 # Store type spec
229 if isinstance(input_tensor, keras_tensor.KerasTensor) or (
230 tf_utils.is_extension_type(input_tensor)):
231 self._type_spec = input_tensor._type_spec # pylint: disable=protected-access
232 else:
233 self._type_spec = tensor_spec.TensorSpec(
234 shape=input_tensor.shape, dtype=input_tensor.dtype, name=self.name)
236 def get_config(self):
237 if self._init_type_spec is not None:
238 config = {
239 'name': self.name,
240 'type_spec': self._init_type_spec
241 }
242 else:
243 config = {
244 'batch_input_shape': self._batch_input_shape,
245 'dtype': self.dtype,
246 'sparse': self.sparse,
247 'ragged': self.ragged,
248 'name': self.name,
249 }
250 return config
252 @property
253 def _trackable_saved_model_saver(self):
254 return layer_serialization.InputLayerSavedModelSaver(self)
257@keras_export('keras.Input', 'keras.layers.Input')
258def Input( # pylint: disable=invalid-name
259 shape=None,
260 batch_size=None,
261 name=None,
262 dtype=None,
263 sparse=None,
264 tensor=None,
265 ragged=None,
266 type_spec=None,
267 **kwargs):
268 """`Input()` is used to instantiate a Keras tensor.
270 A Keras tensor is a symbolic tensor-like object,
271 which we augment with certain attributes that allow us to build a Keras model
272 just by knowing the inputs and outputs of the model.
274 For instance, if `a`, `b` and `c` are Keras tensors,
275 it becomes possible to do:
276 `model = Model(input=[a, b], output=c)`
278 Args:
279 shape: A shape tuple (integers), not including the batch size.
280 For instance, `shape=(32,)` indicates that the expected input
281 will be batches of 32-dimensional vectors. Elements of this tuple
282 can be None; 'None' elements represent dimensions where the shape is
283 not known.
284 batch_size: optional static batch size (integer).
285 name: An optional name string for the layer.
286 Should be unique in a model (do not reuse the same name twice).
287 It will be autogenerated if it isn't provided.
288 dtype: The data type expected by the input, as a string
289 (`float32`, `float64`, `int32`...)
290 sparse: A boolean specifying whether the placeholder to be created is
291 sparse. Only one of 'ragged' and 'sparse' can be True. Note that,
292 if `sparse` is False, sparse tensors can still be passed into the
293 input - they will be densified with a default value of 0.
294 tensor: Optional existing tensor to wrap into the `Input` layer.
295 If set, the layer will use the `tf.TypeSpec` of this tensor rather
296 than creating a new placeholder tensor.
297 ragged: A boolean specifying whether the placeholder to be created is
298 ragged. Only one of 'ragged' and 'sparse' can be True. In this case,
299 values of 'None' in the 'shape' argument represent ragged dimensions.
300 For more information about RaggedTensors, see
301 [this guide](https://www.tensorflow.org/guide/ragged_tensors).
302 type_spec: A `tf.TypeSpec` object to create the input placeholder from.
303 When provided, all other args except name must be None.
304 **kwargs: deprecated arguments support. Supports `batch_shape` and
305 `batch_input_shape`.
307 Returns:
308 A `tensor`.
310 Example:
312 ```python
313 # this is a logistic regression in Keras
314 x = Input(shape=(32,))
315 y = Dense(16, activation='softmax')(x)
316 model = Model(x, y)
317 ```
319 Note that even if eager execution is enabled,
320 `Input` produces a symbolic tensor-like object (i.e. a placeholder).
321 This symbolic tensor-like object can be used with lower-level
322 TensorFlow ops that take tensors as inputs, as such:
324 ```python
325 x = Input(shape=(32,))
326 y = tf.square(x) # This op will be treated like a layer
327 model = Model(x, y)
328 ```
330 (This behavior does not work for higher-order TensorFlow APIs such as
331 control flow and being directly watched by a `tf.GradientTape`).
333 However, the resulting model will not track any variables that were
334 used as inputs to TensorFlow ops. All variable usages must happen within
335 Keras layers to make sure they will be tracked by the model's weights.
337 The Keras Input can also create a placeholder from an arbitrary `tf.TypeSpec`,
338 e.g:
340 ```python
341 x = Input(type_spec=tf.RaggedTensorSpec(shape=[None, None],
342 dtype=tf.float32, ragged_rank=1))
343 y = x.values
344 model = Model(x, y)
345 ```
346 When passing an arbitrary `tf.TypeSpec`, it must represent the signature of an
347 entire batch instead of just one example.
349 Raises:
350 ValueError: If both `sparse` and `ragged` are provided.
351 ValueError: If both `shape` and (`batch_input_shape` or `batch_shape`) are
352 provided.
353 ValueError: If `shape`, `tensor` and `type_spec` are None.
354 ValueError: If arguments besides `type_spec` are non-None while `type_spec`
355 is passed.
356 ValueError: if any unrecognized parameters are provided.
357 """
358 if sparse and ragged:
359 raise ValueError(
360 'Cannot set both sparse and ragged to True in a Keras input.')
362 input_layer_config = {'name': name, 'dtype': dtype, 'sparse': sparse,
363 'ragged': ragged, 'input_tensor': tensor,
364 'type_spec': type_spec}
366 batch_input_shape = kwargs.pop('batch_input_shape',
367 kwargs.pop('batch_shape', None))
368 if shape is not None and batch_input_shape is not None:
369 raise ValueError('Only provide the `shape` OR `batch_input_shape` argument '
370 'to Input, not both at the same time.')
371 if (batch_input_shape is None and shape is None and tensor is None
372 and type_spec is None):
373 raise ValueError('Please provide to Input a `shape`'
374 ' or a `tensor` or a `type_spec` argument. Note that '
375 '`shape` does not include the batch '
376 'dimension.')
377 if kwargs:
378 raise ValueError('Unrecognized keyword arguments:', kwargs.keys())
380 if batch_input_shape:
381 shape = batch_input_shape[1:]
382 input_layer_config.update({'batch_input_shape': batch_input_shape})
383 else:
384 input_layer_config.update(
385 {'batch_size': batch_size, 'input_shape': shape})
386 input_layer = InputLayer(**input_layer_config)
388 # Return tensor including `_keras_history`.
389 # Note that in this case train_output and test_output are the same pointer.
390 outputs = input_layer._inbound_nodes[0].outputs
391 if isinstance(outputs, list) and len(outputs) == 1:
392 return outputs[0]
393 else:
394 return outputs