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`). 17""" 18from __future__ import absolute_import 19from __future__ import division 20from __future__ import print_function 21 22from tensorflow.python.framework import tensor_shape 23from tensorflow.python.keras import backend 24from tensorflow.python.keras.engine import base_layer 25from tensorflow.python.keras.utils import tf_utils 26from tensorflow.python.util.tf_export import keras_export 27 28 29@keras_export('keras.layers.InputLayer') 30class InputLayer(base_layer.Layer): 31 """Layer to be used as an entry point into a Network (a graph of layers). 32 33 It can either wrap an existing tensor (pass an `input_tensor` argument) 34 or create its a placeholder tensor (pass arguments `input_shape`, and 35 optionally, `dtype`). 36 37 It is generally recommend to use the functional layer API via `Input`, 38 (which creates an `InputLayer`) without directly using `InputLayer`. 39 40 Arguments: 41 input_shape: Shape tuple (not including the batch axis), or `TensorShape` 42 instance (not including the batch axis). 43 batch_size: Optional input batch size (integer or None). 44 dtype: Datatype of the input. 45 input_tensor: Optional tensor to use as layer input 46 instead of creating a placeholder. 47 sparse: Boolean, whether the placeholder created 48 is meant to be sparse. 49 name: Name of the layer (string). 50 """ 51 52 def __init__(self, 53 input_shape=None, 54 batch_size=None, 55 dtype=None, 56 input_tensor=None, 57 sparse=False, 58 name=None, 59 **kwargs): 60 if 'batch_input_shape' in kwargs: 61 batch_input_shape = kwargs.pop('batch_input_shape') 62 if input_shape and batch_input_shape: 63 raise ValueError('Only provide the input_shape OR ' 64 'batch_input_shape argument to ' 65 'InputLayer, not both at the same time.') 66 batch_size = batch_input_shape[0] 67 input_shape = batch_input_shape[1:] 68 if kwargs: 69 raise ValueError('Unrecognized keyword arguments:', kwargs.keys()) 70 71 if not name: 72 prefix = 'input' 73 name = prefix + '_' + str(backend.get_uid(prefix)) 74 75 if not dtype: 76 if input_tensor is None: 77 dtype = backend.floatx() 78 else: 79 dtype = backend.dtype(input_tensor) 80 elif input_tensor is not None and input_tensor.dtype != dtype: 81 raise ValueError('`input_tensor.dtype` differs from `dtype`: %s vs. %s' % 82 (input_tensor.dtype, dtype)) 83 super(InputLayer, self).__init__(dtype=dtype, name=name) 84 self.built = True 85 self.sparse = sparse 86 self.batch_size = batch_size 87 self.supports_masking = True 88 89 if isinstance(input_shape, tensor_shape.TensorShape): 90 input_shape = tuple(input_shape.as_list()) 91 92 if input_tensor is None: 93 if input_shape is not None: 94 batch_input_shape = (batch_size,) + tuple(input_shape) 95 else: 96 batch_input_shape = None 97 graph = backend.get_graph() 98 with graph.as_default(): 99 # In graph mode, create a graph placeholder to call the layer on. 100 if sparse: 101 input_tensor = backend.placeholder( 102 shape=batch_input_shape, 103 dtype=dtype, 104 name=self.name, 105 sparse=True) 106 else: 107 input_tensor = backend.placeholder( 108 shape=batch_input_shape, 109 dtype=dtype, 110 name=self.name) 111 112 self.is_placeholder = True 113 self._batch_input_shape = batch_input_shape 114 else: 115 if not tf_utils.is_symbolic_tensor(input_tensor): 116 raise ValueError('You should not pass an EagerTensor to `Input`. ' 117 'For example, instead of creating an ' 118 'InputLayer, you should instantiate your model and ' 119 'directly call it on your input.') 120 self.is_placeholder = False 121 self._batch_input_shape = tuple(input_tensor.get_shape().as_list()) 122 123 # Create an input node to add to self.outbound_node 124 # and set output_tensors' _keras_history. 125 input_tensor._keras_history = (self, 0, 0) # pylint: disable=protected-access 126 input_tensor._keras_mask = None 127 base_layer.Node( 128 self, 129 inbound_layers=[], 130 node_indices=[], 131 tensor_indices=[], 132 input_tensors=[input_tensor], 133 output_tensors=[input_tensor]) 134 135 def get_config(self): 136 config = { 137 'batch_input_shape': self._batch_input_shape, 138 'dtype': self.dtype, 139 'sparse': self.sparse, 140 'name': self.name 141 } 142 return config 143 144 145@keras_export('keras.layers.Input', 'keras.Input') 146def Input( # pylint: disable=invalid-name 147 shape=None, 148 batch_size=None, 149 name=None, 150 dtype=None, 151 sparse=False, 152 tensor=None, 153 **kwargs): 154 """`Input()` is used to instantiate a Keras tensor. 155 156 A Keras tensor is a tensor object from the underlying backend 157 (Theano or TensorFlow), which we augment with certain 158 attributes that allow us to build a Keras model 159 just by knowing the inputs and outputs of the model. 160 161 For instance, if a, b and c are Keras tensors, 162 it becomes possible to do: 163 `model = Model(input=[a, b], output=c)` 164 165 The added Keras attribute is: 166 `_keras_history`: Last layer applied to the tensor. 167 the entire layer graph is retrievable from that layer, 168 recursively. 169 170 Arguments: 171 shape: A shape tuple (integers), not including the batch size. 172 For instance, `shape=(32,)` indicates that the expected input 173 will be batches of 32-dimensional vectors. 174 batch_size: optional static batch size (integer). 175 name: An optional name string for the layer. 176 Should be unique in a model (do not reuse the same name twice). 177 It will be autogenerated if it isn't provided. 178 dtype: The data type expected by the input, as a string 179 (`float32`, `float64`, `int32`...) 180 sparse: A boolean specifying whether the placeholder 181 to be created is sparse. 182 tensor: Optional existing tensor to wrap into the `Input` layer. 183 If set, the layer will not create a placeholder tensor. 184 **kwargs: deprecated arguments support. 185 186 Returns: 187 A tensor. 188 189 Example: 190 191 ```python 192 # this is a logistic regression in Keras 193 x = Input(shape=(32,)) 194 y = Dense(16, activation='softmax')(x) 195 model = Model(x, y) 196 ``` 197 198 Note that even if eager execution is enabled, 199 `Input` produces a symbolic tensor (i.e. a placeholder). 200 This symbolic tensor can be used with other 201 TensorFlow ops, as such: 202 203 ```python 204 x = Input(shape=(32,)) 205 y = tf.square(x) 206 ``` 207 208 Raises: 209 ValueError: in case of invalid arguments. 210 """ 211 if 'batch_shape' in kwargs: 212 batch_shape = kwargs.pop('batch_shape') 213 if shape and batch_shape: 214 raise ValueError('Only provide the shape OR ' 215 'batch_shape argument to ' 216 'Input, not both at the same time.') 217 batch_size = batch_shape[0] 218 shape = batch_shape[1:] 219 if kwargs: 220 raise ValueError('Unrecognized keyword arguments:', kwargs.keys()) 221 222 if shape is None and tensor is None: 223 raise ValueError('Please provide to Input either a `shape`' 224 ' or a `tensor` argument. Note that ' 225 '`shape` does not include the batch ' 226 'dimension.') 227 input_layer = InputLayer( 228 input_shape=shape, 229 batch_size=batch_size, 230 name=name, 231 dtype=dtype, 232 sparse=sparse, 233 input_tensor=tensor) 234 # Return tensor including `_keras_history`. 235 # Note that in this case train_output and test_output are the same pointer. 236 outputs = input_layer._inbound_nodes[0].output_tensors 237 if len(outputs) == 1: 238 return outputs[0] 239 else: 240 return outputs 241