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

Multi-input RNN and TimeDistributed wrapper #3432

Closed
wants to merge 11 commits into from

Conversation

farizrahman4u
Copy link
Contributor

@farizrahman4u farizrahman4u commented Aug 9, 2016

Theano scan op allows looping through multiple sequences simultaneously, but this feature is currently hidden by Keras's abstraction, forcing users to concatenate sequences(followed by unpacking them in the step function).

  • Backward compatible. The API is pretty simple; now the inputs argument can be a tensor or a list of tensors with same input lengths.

@farizrahman4u farizrahman4u changed the title Multi-input RNN Multi-input RNN and TimeDistributed wrapper Aug 9, 2016
@farizrahman4u
Copy link
Contributor Author

Also see #3057

@farizrahman4u farizrahman4u reopened this Aug 9, 2016
@farizrahman4u
Copy link
Contributor Author

ping @fchollet

x = tf.transpose(x, (axes))
input_list += [tf.unpack(x)]
assert len(set(map(len, input_list))) == 1, "All input sequences should be of equal length."
input_list = [map(lambda x: x[t], input_list) for t in range(len(input_list[0]))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If feel like this should be handled more elegantly in the above loop. This line is not very readable.

ndim = len(x.get_shape())
assert ndim >= 3, "Input should be at least 3D."
for t in range(input_length):
input_list[t] += [x[(slice(None), t) + (slice(None),) * (ndim - 2)]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation issue. Are you using a linter (like pylint)?

@fchollet
Copy link
Member

Can you describe what is the motivation for this feature? Would it be used anywhere?

@farizrahman4u
Copy link
Contributor Author

farizrahman4u commented Aug 13, 2016

I currently use it in a couple of custom layers. The RNN scans through multiple sequences, and at each time step, an element from only one of the sequences is chosen, based on a hidden state.

inputs = tf.transpose(inputs, (axes))
input_list = tf.unpack(inputs)
if type(inputs) == list:
input_list = [[]] * input_length
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>>> input_list = [[]] * 10
>>> input_list[0] += [1]
>>> input_list
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]

Probably not what you intended.

@matt-gardner
Copy link
Contributor

Here's another use case for this feature: we are building reading comprehension models and memory networks using Keras. To answer a question, we perform some multi-step operations on the input question, answer candidate, and a passage of text. If the question is multiple choice, it would be really convenient to be able to just TimeDistribute each of those multi-step operations, and have a softmax at the end to select an answer option. But because TimeDistributed only takes a single input, we have to go through a bunch of contortions of merging the inputs in funny ways and unpacking them in our Layer classes. It would simplify a whole lot of parts of our code if we could just pass several inputs into TimeDistributed.

@farizrahman4u
Copy link
Contributor Author

@matt-gardner Unfortunately, this PR is way too old for me to get back at it. You can add your unpacking logic as a Lambda layer to a model, and then add your layer to the model. Since models are layers by inheritance, you can timedistribute the model.

@farizrahman4u farizrahman4u deleted the patch-14 branch June 3, 2017 00:27
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

Successfully merging this pull request may close these issues.

None yet

3 participants