Hi all,
I have the following (stateful) function, which integrates an input into a
persistent variable, and outputs a rounded version of that. The function
is demonstrated here.
import numpy as np
import theano
import theano.tensor as tt
from theano.ifelse import ifelse
def int_and_fire(x):
# Integrate inputs until crossing threshold and then reset. Output integers
phi = theano.shared(np.zeros((0,) * x.ndim))
phi_ = ifelse(phi.size > 0, phi + x, x) # Enters "False" condition only on
first call.
s = tt.round(phi_)
return s, {phi: phi_-s}
inp = tt.vector()
out, updates = int_and_fire(inp)
f = theano.function(inputs=[inp], outputs=out, updates=updates)
xs = np.random.randn(20, 10)
ys = np.array([f(x) for x in xs]) # This works fine
assert ys.shape==(20, 10)
It uses the "ifelse" trick (suggested here
<https://groups.google.com/d/msg/theano-users/pFcCxROBC5k/lGPtEDq9J0sJ>) to
initialize the internal variable (phi) to the shape of the input (which is
not known until call-time). This works fine - you can compile the
function, and call it in a loop, as shown above.
Now, the problem is when I want to move my loop into theano. Continuing
the above code, I add:
*# <Code from previous snippet>*
def int_and_fire_batch(xs):
"""
:param xs: An (n_samples, ...) array
:return: An (n_samples, ...) array
"""
out, updates = theano.scan(int_and_fire, sequences=[xs])
return out, updates
inp2 = tt.matrix()
out2, updates2 = int_and_fire_batch(inp2)
f2 = theano.function(inputs=[inp2], outputs=out2, updates=updates2)
ys2 = f2(xs) # <-- Fails here
assert ys2.shape==(20, 10)
assert np.allclose(ys2, ys)
But it fail on the line ys2 = f2(xs), with
ValueError: could not broadcast input array from shape (10) into shape (0)
The problem appears to be that it doesn't like the fact that the shared
variable phi has shape (0, ) on the first iteration, and (10, ) thereafter.
So my question: *Is there some way that I can have a persistent variable
whose shape is initialized to match the input, and to use this function
within a scan loop?*
Full code, in to case you want to try:
import numpy as np
import theano
import theano.tensor as tt
from theano.ifelse import ifelse
def int_and_fire(x):
# Integrate inputs until crossing threshold and then reset. Output integers
phi = theano.shared(np.zeros((0,) * x.ndim))
phi_ = ifelse(phi.size > 0, phi + x, x) # Enters "False" condition only on
first call.
s = tt.round(phi_)
return s, {phi: phi_-s}
inp = tt.vector()
out, updates = int_and_fire(inp)
f = theano.function(inputs=[inp], outputs=out, updates=updates)
xs = np.random.randn(20, 10)
ys = np.array([f(x) for x in xs]) # This works fine
assert ys.shape==(20, 10)
def int_and_fire_batch(xs):
"""
:param xs: An (n_samples, ...) array
:return: An (n_samples, ...) array
"""
out, updates = theano.scan(int_and_fire, sequences=[xs])
return out, updates
inp2 = tt.matrix()
out2, updates2 = int_and_fire_batch(inp2)
f2 = theano.function(inputs=[inp2], outputs=out2, updates=updates2)
ys2 = f2(xs) # <-- Fails here
assert ys2.shape==(20, 10)
assert np.allclose(ys2, ys)
--
---
You received this message because you are subscribed to the Google Groups
"theano-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.