Hi all,
I’m new to PyMC (thanks to the community and the contributors for this amazing library!). I’m developing a BVAR model that should, in principle, work with the state-space implementation. While I’ve managed to set up most of the model correctly, I’ve hit a roadblock that I can’t seem to resolve.
When I use the following code:
state_chol, _, _ = pm.LKJCholeskyCov(
"state_chol", eta=2, n=m, # Only for the stationary part (2x2)
sd_dist=sd_dist
)
state_cov_stationary = pm.Deterministic("state_cov_stationary", state_chol @ state_chol.T)
The model runs smoothly. However, I want to use the inverse Wishart distribution that is invariant to the order of the variables. For this, I implemented:
nu = pm.ConstantData("nu", m + 4)
V = pm.ConstantData("V", np.eye(len(bvar_trends.stationary_var_names)))
Sigma_draws = inverse_wishart_dist(nu, V)
Here’s my implementation of inverse_wishart_dist
:
def inverse_wishart_dist(nu: pt.TensorVariable, V: pt.TensorVariable):
def random(nu, V, size=None, rng=None):
if rng is None:
rng = np.random.default_rng()
nu_val = float(np.asarray(nu).item())
X = stats.wishart.rvs(df=nu_val, scale=np.linalg.inv(V), random_state=rng)
Sigma = np.linalg.inv(X)
return (Sigma + Sigma.T) / 2 + np.eye(V.shape[0]) * 1e-6
def logp(value, nu, V):
sign, logdet = pt.nlinalg.slogdet(value)
if sign <= 0:
return -np.inf
log_det_v = pt.nlinalg.slogdet(V)[1]
n_stationary = V.shape[0]
log_det_terms = (nu / 2) * log_det_v - ((nu + n_stationary + 1) / 2) * logdet
trace_term = -0.5 * pt.nlinalg.trace(V @ pt.linalg.inv(value))
return log_det_terms + trace_term
return pm.CustomDist(
"InverseWishart",
nu,
V,
random=random,
logp=logp,
ndim_supp=2,
ndims_params=[0, 2],
signature="(),(m,m)->(m,m)",
dtype="float64"
)
However, when I try to use this custom distribution, I encounter an error:
“logp function depends on a random variable.”
I’m unsure how to resolve this issue.
Has anyone encountered a similar problem or have suggestions on how to address this? Any help would be greatly appreciated!
Thanks in advance!
Andres