"""Input layer code (`Input` and `InputLayer`).
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from .base_layer import Layer
from .base_layer import Node
from .. import backend as K
from ..legacy import interfaces
from ..utils.generic_utils import unpack_singleton
class InputLayer(Layer):
"""Layer to be used as an entry point into a model.
It can either wrap an existing tensor (pass an `input_tensor` argument)
or create its a placeholder tensor (pass arguments `input_shape`
or `batch_input_shape` as well as `dtype`).
# Arguments
input_shape: Shape tuple, not including the batch axis.
batch_size: Optional input batch size (integer or None).
batch_input_shape: Shape tuple, including the batch axis.
dtype: Datatype of the input.
input_tensor: Optional tensor to use as layer input
instead of creating a placeholder.
sparse: Boolean, whether the placeholder created
is meant to be sparse.
name: Name of the layer (string).
"""
@interfaces.legacy_input_support
def __init__(self, input_shape=None, batch_size=None,
batch_input_shape=None,
dtype=None, input_tensor=None, sparse=False, name=None):
if not name:
prefix = 'input'
name = prefix + '_' + str(K.get_uid(prefix))
super(InputLayer, self).__init__(dtype=dtype, name=name)
self.trainable = False
self.built = True
self.sparse = sparse
self.supports_masking = True
if input_shape and batch_input_shape:
raise ValueError('Only provide the input_shape OR '
'batch_input_shape argument to '
'InputLayer, not both at the same time.')
if input_tensor is not None and batch_input_shape is None:
# If input_tensor is set, and batch_input_shape is not set:
# Attempt automatic input shape inference.
try:
batch_input_shape = K.int_shape(input_tensor)
except TypeError:
if not input_shape and not batch_input_shape:
raise ValueError('InputLayer was provided '
'an input_tensor argument, '
'but its input shape cannot be '
'automatically inferred. '
'You should pass an input_shape or '
'batch_input_shape argument.')
if not batch_input_shape:
if not input_shape:
raise ValueError('An Input layer should be passed either '
'a `batch_input_shape` or an `input_shape`.')
else:
batch_input_shape = (batch_size,) + tuple(input_shape)
else:
batch_input_shape = tuple(batch_input_shape)
if not dtype:
if input_tensor is None:
dtype = K.floatx()
else:
dtype = K.dtype(input_tensor)
self.batch_input_shape = batch_input_shape
self.dtype = dtype
if input_tensor is None:
self.is_placeholder = True
input_tensor = K.placeholder(shape=batch_input_shape,
dtype=dtype,
sparse=self.sparse,
name=self.name)
else:
self.is_placeholder = False
input_tensor._keras_shape = batch_input_shape
# Create an input node to add to self.outbound_node
# and set output_tensors' _keras_history.
input_tensor._uses_learning_phase = False
input_tensor._keras_history = (self, 0, 0)
Node(self,
inbound_layers=[],
node_indices=[],
tensor_indices=[],
input_tensors=[input_tensor],
output_tensors=[input_tensor],
input_masks=[None],
output_masks=[None],
input_shapes=[batch_input_shape],
output_shapes=[batch_input_shape])
def get_config(self):
config = {'batch_input_shape': self.batch_input_shape,
'dtype': self.dtype,
'sparse': self.sparse,
'name': self.name}
return config
def Input(shape=None, batch_shape=None,
name=None, dtype=None, sparse=False,
tensor=None):
"""`Input()` is used to instantiate a Keras tensor.
A Keras tensor is a tensor object from the underlying backend
(Theano, TensorFlow or CNTK), which we augment with certain
attributes that allow us to build a Keras model
just by knowing the inputs and outputs of the model.
For instance, if a, b and c are Keras tensors,
it becomes possible to do:
`model = Model(input=[a, b], output=c)`
The added Keras attributes are:
`_keras_shape`: Integer shape tuple propagated
via Keras-side shape inference.
`_keras_history`: Last layer applied to the tensor.
the entire layer graph is retrievable from that layer,
recursively.
# Arguments
shape: A shape tuple (integer), not including the batch size.
For instance, `shape=(32,)` indicates that the expected input
will be batches of 32-dimensional vectors.
batch_shape: A shape tuple (integer), including the batch size.
For instance, `batch_shape=(10, 32)` indicates that
the expected input will be batches of 10 32-dimensional vectors.
`batch_shape=(None, 32)` indicates batches of an arbitrary number
of 32-dimensional vectors.
name: An optional name string for the layer.
Should be unique in a model (do not reuse the same name twice).
It will be autogenerated if it isn't provided.
dtype: The data type expected by the input, as a string
(`float32`, `float64`, `int32`...)
sparse: A boolean specifying whether the placeholder
to be created is sparse.
tensor: Optional existing tensor to wrap into the `Input` layer.
If set, the layer will not create a placeholder tensor.
# Returns
A tensor.
# Example
```python
# this is a logistic regression in Keras
x = Input(shape=(32,))
y = Dense(16, activation='softmax')(x)
model = Model(x, y)
```
"""
if not batch_shape and tensor is None:
assert shape is not None, ('Please provide to Input either a `shape`'
' or a `batch_shape` argument. Note that '
'`shape` does not include the batch '
'dimension.')
if shape is not None and not batch_shape:
batch_shape = (None,) + tuple(shape)
if not dtype:
dtype = K.floatx()
input_layer = InputLayer(batch_input_shape=batch_shape,
name=name, dtype=dtype,
sparse=sparse,
input_tensor=tensor)
# Return tensor including _keras_shape and _keras_history.
# Note that in this case train_output and test_output are the same pointer.
outputs = input_layer._inbound_nodes[0].output_tensors
return unpack_singleton(outputs)