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.

Reply via email to