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

Scan cannot include MRG_RandomStreams.binomial with symbolic shape #3437

Closed
f0k opened this issue Sep 24, 2015 · 6 comments
Closed

Scan cannot include MRG_RandomStreams.binomial with symbolic shape #3437

f0k opened this issue Sep 24, 2015 · 6 comments

Comments

@f0k
Copy link
Contributor

f0k commented Sep 24, 2015

scan cannot have a MRG_RandomStreams.binomial in its step function that uses the symbolic shape of a recurrent variable: It fails to compile with a MissingInputError. This was discovered by a Lasagne user some days ago (https://groups.google.com/forum/#!topic/lasagne-users/8E1iR04_nK8), and a few minutes ago a colleague stumbled upon the same problem, so I think it might deserve some attention. (I've read that dropouts in recurrent connections don't work well in practice, but this shouldn't be a reason to refuse compilation ;).)

The following code demonstrates that scan works fine with a nonsymbolic shape in binomial, but fails with a symbolic shape:

import theano
import theano.tensor as T
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
floatX = theano.config.floatX

inputs = T.matrix()
hid_init = T.vector()
rng = RandomStreams()

# Works:
def step(inp, prev):
    # rng.binomial with constant shape
    return inp + prev * rng.binomial((10,), p=.5, dtype=floatX)
out = theano.scan(step, sequences=[inputs], outputs_info=[hid_init])[0]
theano.function([inputs, hid_init], out)
print "Success!"

# Fails:
def step(inp, prev):
    # rng.binomial with symbolic shape
    return inp + prev * rng.binomial(prev.shape, p=.5, dtype=floatX)
out = theano.scan(step, sequences=[inputs], outputs_info=[hid_init])[0]
theano.function([inputs, hid_init], out)
print "Will never be reached!"

The error is:

theano.gof.fg.MissingInputError: ("An input of the graph, used to compute Shape(<TensorType(float32, vector)>), was not provided and not given a value.Use the Theano flag exception_verbosity='high',for more information on this error.", <TensorType(float32, vector)>)
@carriepl
Copy link
Contributor

The error comes from the fact that the 'updates' output of Scan is not provided to function(). It works with the following code :

# Works:
def step(inp, prev):
    # rng.binomial with constant shape
    return inp + prev * rng.binomial((10,), p=.5, dtype=floatX)
out, updates = theano.scan(step, sequences=[inputs], outputs_info=[hid_init])
theano.function([inputs, hid_init], out, updates=updates)
print "Success!"

# Fails:
def step(inp, prev):
    # rng.binomial with symbolic shape
    return inp + prev * rng.binomial(inp.shape, p=.5, dtype=floatX)
out, updates = theano.scan(step, sequences=[inputs], outputs_info=[hid_init])
theano.function([inputs, hid_init], out, updates=updates)
print "Will never be reached!"

@f0k
Copy link
Contributor Author

f0k commented Sep 25, 2015

Oh, of course. Interesting behaviour, though. Thanks a lot!

@carriepl
Copy link
Contributor

I agree 100% that this is weird behaviour. We should either :
-find a way such that the user doesn't need to perform this updates management or
-find a way to detect the case where the user should have provided the updates and didn't and display an informative error message.

@f0k
Copy link
Contributor Author

f0k commented Sep 25, 2015

find a way such that the user doesn't need to perform this updates management

This would be great. For uses of RNGs outside of scan, updates are handled transparently already. If this isn't possible for scan, the API in Lasagne will have to become a little more complex to cater for that (not a deal breaker, but would make recurrent layers a bit cumbersome).

@apeterswu
Copy link

Hi,
I met the same error. So is there any solution if I need to use in scan?

@f0k
Copy link
Contributor Author

f0k commented Jul 10, 2017

So is there any solution if I need to use in scan?

As mentioned in #3437 (comment), it should be enough to capture the updates returned by theano.scan() and make sure they are passed on to theano.function() and not just discarded.

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

3 participants