Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recurrent layer not accepting multiple inputs list despite source code seemingly handling such case #5986

Closed
fferroni opened this issue Mar 26, 2017 · 5 comments

Comments

@fferroni
Copy link

Hello,

Reading the source code for Recurrent.py, it would appear that a layer like LSTM would be able to accept multiple input tensors. In call() of Recurrent, I see an option like ifinstance(inputs, list) then it will pick the first element of that list to be the input data tensor, and the rest as initial_states presumably.

https://github.com/fchollet/keras/blob/ec9c95fdbd60c2d86288858563c57b0007b24430/keras/layers/recurrent.py#L263

 def call(self, inputs, mask=None, initial_state=None, training=None):
        # input shape: `(samples, time (padded with zeros), input_dim)`
        # note that the .build() method of subclasses MUST define
        # self.input_spec and self.state_spec with complete input shapes.
        if initial_state is not None:
            if not isinstance(initial_state, (list, tuple)):
                initial_states = [initial_state]
            else:
                initial_states = list(initial_state)
        if isinstance(inputs, list):
            initial_states = inputs[1:]
            inputs = inputs[0]

However, if I run a simple script like such

import numpy as np
from keras.models import Model
from keras.layers import LSTM, Input

data_input = Input(shape=(10,5))
time_input = Input(shape=(10,1))

asynchronous = LSTM(15)([data_input, time_input])
model = Model(inputs=[data_input, time_input], outputs=asynchronous)

I get the following exception:

Traceback (most recent call last):
  File "ras.py", line 24, in <module>
    main()
  File "ras.py", line 16, in main
    asynchronous = LSTM(15)([data_input, time_input])
  File "/usr/local/lib/python2.7/dist-packages/keras/layers/recurrent.py", line 252, in __call__
    return super(Recurrent, self).__call__(inputs, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/topology.py", line 511, in __call__
    self.assert_input_compatibility(inputs)
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/topology.py", line 401, in assert_input_compatibility
    str(input))
ValueError: Layer lstm_1 expects 1 inputs, but it received 2 input tensors. Input received: <built-in function input>

I am actually trying to write a custom layer which requires two input tensors than inherits from Recurrent, but I am not sure whether I need to change the Recurrent class as well at this point... from the source code it would appear it can accept a list, and it would just use the first element of that list as the main input tensor. Can someone clarify?

@Joshua-Chin
Copy link
Contributor

This will be fixed by #5795. We're currently waiting for someone to review it.

@stale stale bot added the stale label Jun 25, 2017
@stale
Copy link

stale bot commented Jun 25, 2017

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 30 days if no further activity occurs, but feel free to re-open a closed issue if needed.

@jmhessel
Copy link
Contributor

FYI, for folks reading this -- I was running into some trouble with RNNs not accepting multiple inputs. Turns out the solution was to modify the input_spec, i.e., do: self.input_spec = [InputSpec(ndim=3), InputSpec(ndim=...)]

@stale stale bot removed the stale label Jun 30, 2017
@stale
Copy link

stale bot commented Sep 28, 2017

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 30 days if no further activity occurs, but feel free to re-open a closed issue if needed.

@stale stale bot added the stale label Sep 28, 2017
@stale stale bot closed this as completed Oct 28, 2017
@aviziskind
Copy link

aviziskind commented Oct 28, 2018

This still appears to be an issue (I'm using keras 2.0.8). I have implemented my own layer that inherits from recurrent, but get a similar error when I try to pass in multiple inputs as a list. I did specify the input_spec when I initialize the layer as @jmhessel suggested, but this does not help. The issue first arises in the following lines of code from recurrent.py from call:

    def call(self, inputs, mask=None, training=None, initial_state=None):
        # input shape: `(samples, time (padded with zeros), input_dim)`
        # note that the .build() method of subclasses MUST define
        # self.input_spec and self.state_spec with complete input shapes.
        if isinstance(inputs, list):
            initial_state = inputs[1:]
            inputs = inputs[0]
        elif initial_state is not None:
            pass
        elif self.stateful:
            initial_state = self.states
        else:
            initial_state = self.get_initial_state(inputs)

The assumption in these lines of code is that if the input is a list, then the input is the first element in the list, and the following items are the initial state (even if the initial_state is specified explicitly). I tried modifying this function to remove this assumption (ie. not split up the inputs in this way if the initial_state is specified), but then an error gets raised a few lines later during the call to rnn (tensorflow_backend.py, line 2332, at the beginning of the function:

def rnn(step_function, inputs, initial_states,
        go_backwards=False, mask=None, constants=None,
        unroll=False, input_length=None):
    """Iterates over the time dimension of a tensor.
...
# inputs: tensor of temporal data of shape `(samples, time, ...)`  # <-- confirming the assumption that a single tensor is expected.
#            (at least 3D).
...
ndim = len(inputs.get_shape())    # <-- raises the error: "AttributeError: 'list' object has no attribute 'get_shape'"

which again assumes that inputs is a single tensor, and not a list of inputs, an assumption that I see is present in the rest of that function as well, including the specification of the inputs argument in the docstring. Can I conclude that the recurrent layer does not support multiple inputs in the form of a list, or am I missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants