Mass Matrix contains zero Error. Scaling data with a diagonal matrix of random variables

Hello, I’ve been having trouble writing a probabilistic model in PyMC3. I’m trying to take a (M X 3) data matrix and multiply it by another matrix with random variables on the diagonal, therefore scaling the matrix columns.

using NumPy it would be

  Y = data @ np.diagflat(L))  

Where L is a (3, 1) array of Uniform Random variables to scale my data. The noise for each of the 3 columns would be normally distributed with the same variance. When I sample from my model I keep getting a ValueError message that the Mass matrix contains zeros on the diagonal? Running PyMC3 v3.9.3

import numpy as np
import pymc3 as pm
import theano.tensor as tt

L = np.random.normal(loc=3, scale=0.25, size=(3,1))     # random scaling
M = 5000    # number of data points
D = 3    # dimensions of data
data = np.random.uniform(low=0, high=20, size=(M, D))      # create fake data
noise = np.random.normal(loc=0.0, scale=0.25, size(M, D))    # create Noise
Y_target = (data @ np.diagflat(L)) + noise     # make target 

with pm.Model() as model_1:
     S = pm.distributions.Uniform("S", lower=0, upper=100, shape =3)
     sigma = pm.HalfNormal("Sigma", sigma =2, shape = 1)
     mu = pm.Deterministic('mu', pm.math.dot(data, tt.diag(S)))

     Y_obs = pm.Normal("Y_obs", mu=mu, sigma=sigma, observed=Y_target, shape =3)

Seems to be just a problem with your prior being too flat. Also you don’t need shape in your Y_obs.

Just replace your uniform dist with

    S = pm.Normal("S", 0,1, shape =3)
1 Like

Thank you. That helped!

1 Like

For

  S = pm.Normal("S" , 0,  1, shape =3)

Can you explain why using shape=(3,1) or shape(1,3) errors but using shape=3 works?

It is because of how tt.diag() works, it would not give you a (3,3) matrix if you supply any of those shapes.

1 Like

I’m having trouble finding documentation on tt.diag() . I would like to understand why it wont return a (3,3) matrix. Do you have any sources I could read?

Can’t find real documentation. But the idea is to construct a symbolic matrix from its diagonal, and so it expects the shape (3,) (from what I can see and tested). Check this post for an example.