# Pymc3 vector concatenation

Hi. Is there a way to group various subsets of random variables into a single vector to use in vector operations? For example, say my model looks something like:

a = pm.Normal(…, shape=4)
b = pm.Normal(…, shape=7)

and I would like to compute something like the dot product of [ a[2], b[1], b[2], b[3], b[4] ] with a 5-element vector x = [x1, x2, x3, x4, x5]. How would I go about doing that?

I have tried doing approximately these two solutions:

vec = pm.math.concatenate( (a[2], b[1:5] )
vec = pm.math.stack( (a[2], b[1:5] )

but I get errors about joining Tensors of different dimensions.

I think I am missing something very simple here, anybody know what it is?

Thanks.

try using

``````import theano.tensor as tt
tt.printing.Print('a')(a.shape)
``````

to find out the shape of `a[2]` and `b[1:5]`.

Also, your sub-vectors are probably 1-dimensional. Try to use the `axis` keyword to explicitly state in which direction to join them, as in

``````pm.math.stack( [ a[2], b[1:5] ] , axis = 0)
``````

(sorry that i cannot test/confirm that atm)

So when I try printing the various shapes, I get that the shape of a[2] is [] and the shape of b[1:5] is [4]. For reference, the shape of a is [4] and the shape of b is [7]. It looks like this is just returning the value of the shape parameter in the respective pm.Normal call.

Your suggestion to specify the axis resulted in the error “TypeError: Join() can only join tensors with the same number of dimensions.” for axis = 0, and “IndexError: axis 1 is out of bounds [-1, 1)” for axis = 1.

I tried one more thing. I guessed that this might be happening because a[2] is a scalar and b[1:5] is a vector, so I attempted pm.math.stack( [ a[2:4], b[1:5] ] , axis = 0). This yielded the error “ValueError: all the input array dimensions except for the concatenation axis must match exactly”.

When you index one element from `a` the result is a scalar, thus the shape error when you are trying to concatenate it with a 1d tensor. You can expand the dimension, or create 2d RVs like

``````a = pm.Normal(…, shape=(4, 1))
b = pm.Normal(…, shape=(7, 1))
``````

This was helpful. I managed to get it working by doing

``````a = pm.Normal(..., shape=(4,1))
b = pm.Normal(..., shape=(7,1))

vec = pm.math.concatenate( (a[2:3], b[1:5]), axis=0)
``````

Printing the shapes showed that `a[2]` does not have the same shape as `a[2:3]`.

Thanks very much for your assistance!

2 Likes

This answer works great, but is there a way to assign `vec` to its own pymc3 variable in the model, and ignore `a` and `b`? I do not need `a` and `b` as standalone parameters in the trace, but would like to use `vec__0`, …, `vec__n`, instead. That way, I can work with a variable number of terms in an N-d linear model where I want different priors for different terms.

You should be able to wrap it in `pm.Deterministic`:

``````vec = pm.Deterministic('vec', pm.math.concatenate( (a[2:3], b[1:5]), axis=0))
``````