• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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