Bounded Distribution for LKJCholCov

I have the following few lines which attempts to put a bounded distribution on the sd_dist parameter of LKJCholeskyCov:

boundedCauchy = pm.Bound(pm.HalfCauchy, upper=1)
sd_α = boundedCauchy('sd_α', beta=0.5)
packed_L_α = pm.LKJCholeskyCov('packed_L_α', n=D, eta=2., sd_dist=sd_α)

However, this results in the error AttributeError: 'TransformedRV' object has no attribute 'logp'. Any thoughts on how to get around this, or if it’s some sort of a bug in the first place?

Thanks!

LKJCholeskyCov doesn’t take a random variable for sd_dist, but a distribution. The difference is that the random variable already has associated parameters, while the distribution is just an object that we can use to get the logp of some variables. Using something like pm.HalfCauchy() you create a random variable, with pm.HalfCauchy.dist() you can create the distribution. Note that the distribution doesn’t have a name parameter, as there is nothing that we’d want to store in the trace. It also doesn’t interact with the model. The reason that LKJCholeskyCov takes a distribution instead of a random variable is that it needs to take control of the parametrization and storage of the standard deviations itself. This also means that the usual way of handling bounded variables via reparametrization won’t work with it, as this would have to happen inside LKJCholeskyCov.
Why do you need that? If you just want to include prior information that the sd is not very large, it would probably be much better to just use a tight pm.HalfNormal prior instead of a truncated half cauchy. Otherwise, I can think of two ways to get what you want:

  • Use a somewhat tight normal distribution around 1 for sd_dist (it is forced to be > 0 anyway, due to the parametrization in LKJCholeskyCov), extract the sd values using tt.sqrt(tt.diag(tt.dot(chol, chol.T))) or so, and rescale the cholesky matrix to have sd values of 1. Then, create the actual standard deviations that you want using pm.Bound as in your code and rescale the cholesky matrix to have those. This probably isn’t exactly efficient, but it should work. You might need to experiment with different choices for sd_dist a bit to find something that the sampler is happy about.
  • Copy the source of LKJCholeskyCov and change the parametrization of the sd_vals. Also make sure to get all those jacobian terms right.
1 Like