I am playing around with autoguides in SVI, and am trying to extract the constrained domain covariance matrix from a successful MultivariateNormal autoguide. I am getting the correct distribution / covariance when drawing samples from the resulting posterior using Predict, but haven’t been able to find the most elegant way to get the raw covariance matrix from which these samples are being drawn.
E.g.:
# ------------------------
# Model
sig1, sig2, theta = 2.0, 5.0, 45*np.pi/180 # True params
def model_forauto():
x = numpyro.sample('x', dist.Uniform( -10 , 10))
y = numpyro.sample('y', dist.Uniform( -10 , 10))
c,s = jnp.cos(theta), jnp.sin(theta)
log_fac = -1.0 / 2.0 * ( ( (c*x- s*y) / sig1 )**2 + ( (s*x + c*y) / sig2)**2 )
numpyro.factor('logfac', log_fac)
# ------------------------
# SVI Work
optimizer_forauto = numpyro.optim.Adam(step_size=0.0005)
autoguide = numpyro.infer.autoguide.AutoMultivariateNormal(model_forauto)
autosvi = SVI(model_forauto, autoguide, optim = optimizer_forauto, loss=Trace_ELBO())
autosvi_result = autosvi.run(random.PRNGKey(1), 50000)
# ------------------------
# Recover Covariance Matrix
L = autosvi_result.params["auto_scale_tril"]
COVAR_REC = jnp.dot(L,L.T)
Doing things this way, I get a covariance matrix with the correct ‘shape’, but multiplied by a factor that changes with prior width, distribution width etc. e.g. for the above, the correct covariance matrix should be:
But I am recovering something that is too small by a factor of ~23.33
I’ve tried various attempts to transform back manually using autoguide.get_transform(params = autosvi_result.params) and its various properties (e.g. the Jacobian determinant) but haven’t found a clear way to recover the scale that generalizes to all cases.
To confirm that the SVI itself is converging correctly, here is a comparison of the true likelihood function (left) to the samples recovered from Predictive(autoguide, params=autosvi_result.params, num_samples=5000)
