Expected an array-like object, but found a Variable

Hi all,

When executing the code below I

theano.config.compute_test_value='warn'
f = theano.function([x], theano.tensor.extra_ops.Unique(False, False, True)(x))

with pm.Model() as model:
           
    gamma = pm.DiscreteUniform('gamma',lower=413,upper=1000)
    delta = pm.DiscreteUniform('delta',lower=1,upper=gamma, shape=(900))
    
    st = f(delta)
    
    step = pm.Metropolis()
    trace = pm.sample(10000, tune=2500, chains=4, cores=4, step=step)

It fails with the following errors

TypeError: Bad input argument with name "delta" to theano function with name "/tmp/ipykernel_4862/3750763553.py:2" at index 0 (0-based).  
Backtrace when that variable is created:

and 

Expected an array-like object, but found a Variable: maybe you are trying to call a function on a (possibly shared) variable instead of a numeric array?

What am I doing wrong?

Regards Hans

There is no need to compile the operation into a theano.function, apply the ops on the tensor directly like:

with pm.Model() as model:
           
    gamma = pm.DiscreteUniform('gamma',lower=413,upper=1000)
    delta = pm.DiscreteUniform('delta',lower=1,upper=gamma, shape=(900))
    
    st = theano.tensor.extra_ops.Unique(False, False, True)(delta)
    ...
3 Likes

Thanks Junpenglao
I struggle a lot with Theano/Pymc3.
E.g. I do not understand why the function does not work

Could I have found out it myself somewhere?

Just to avoid asking questions the next time.

Regards Hans

theano.function is meant for compiling a tensor expression into a callable, so if you have a series of tensor operation outputs = theano.tensor.XX(*inputs), the computation is not actually done as we only build out the rule how you might do the computation when you see the data. theano.function([*inputs], outputs) returns a function like object you can call like a NumPy function. More information is in the doc: function - defines aesara.function — Aesara 2.3.2+17.g79961a625.dirty documentation

More specific, during modeling with PyMC you rarely need to use theano.function, as in the model only tensor are passing around.

One thing I find difficult is understanding the types the pymc3 functions like DiscreteUniform return.

E.g. I can subtract a number from a numpy array which subtracts it from all elements.

When I try to do the same in my model it fails.
How can I do that?

For simple things like these it is hard to find resources.

Thanks Hans

DiscreteUniform is not a function, so the usage is a bit different - in general you use it to create a random variable within a model context (whereas theano/aesara operation works outside the model context as well).

Yes I understand
That makes it so difficult :stuck_out_tongue_closed_eyes:

This worked as per your advice:
st = theano.tensor.extra_ops.Unique(False, False, True)(delta)
But now I want to subtract 1 of the values

a = st - 1
Gives:

TypeError: unsupported operand type(s) for -: ‘list’ and ‘int’

Can you give me a clue?
Do I need theano.scan??

I promise that there will be no more questions in this post :blush:

Regards Hans

No worries! Hopefully you find the answer useful.
theano.tensor.extra_ops.Unique(False, False, True) return unique value and count, so you should do:

unique_value, count = theano.tensor.extra_ops.Unique(False, False, True)(delta)

And subtract the value accordingly.

However, I am not completely sure what you want to do, but since unique_value change length, you probably will have some problem building model on top of it (and sample from this model)

Oh no
That was a no brainer.
Works the same with numpy☺️

I understand your point.
Will rethink it