Singular cholesky error in AutoLaplaceApproximation

I am trying to replicate Code 4.26/4.27 from the Statistical Rethinking book (1st Edition).

def model():
    mu = pyro.sample("mu", dist.Normal(tensor(178.), tensor(20.)))
    sigma = pyro.sample("sigma", dist.Uniform(tensor(0.), tensor(50.)))
    height = pyro.sample("height", dist.Normal(mu, sigma))#,obs=height)
    return height 
    


def guide():
    mu_param = pyro.param(
        "mu_param", tensor(140.)
    )
    sigma_param = pyro.param(
        "sigma_param", tensor(20.), constraint=constraints.positive
    )
    return pyro.sample("mu", dist.Delta(mu_param)), pyro.sample("sigma", dist.Delta(sigma_param))


pyro.clear_param_store()
conditioned = pyro.condition(model, data={"height": tensor(howell2['height'], dtype=torch.float64)})

guide = pyro.infer.autoguide.AutoLaplaceApproximation(conditioned)
laplace_guide = guide.laplace_approximation()
pred = pyro.infer.Predictive(laplace_guide, num_samples=1000)

This results in:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-179-eed6db761efe> in <module>()
     18 
     19 guide = pyro.infer.autoguide.AutoLaplaceApproximation(conditioned)
---> 20 laplace_guide = guide.laplace_approximation()
     21 pred = pyro.infer.Predictive(laplace_guide, num_samples=1000)
     22 p_summary = summary(pred.get_samples(), 0.945).loc[:, ["mu", "sigma"]]

/usr/local/lib/python3.6/dist-packages/pyro/infer/autoguide/guides.py in laplace_approximation(self, *args, **kwargs)
   1033         cov = H.inverse()
   1034         loc = self.loc
-> 1035         scale_tril = cov.cholesky()
   1036 
   1037         gaussian_guide = AutoMultivariateNormal(self.model)

RuntimeError: cholesky_cpu: U(1,1) is zero, singular U.

Any pointers?

you need to train the guide using SVI vbefore you can call laplace_approximation() (there’s no reason a randomly initialized laplace guide should be positive definite)

Thanks, I should have been clearer in my original post. I do train using SVI.

def model():
    mu = pyro.sample("mu", dist.Normal(tensor(178.), tensor(20.)))
    sigma = pyro.sample("sigma", dist.Uniform(0, tensor(50.)))
    height = pyro.sample("height", dist.Normal(mu, sigma))#,obs=height)
    return height 
    


def guide():
    mu_param = pyro.param(
        "mu_param", tensor(140.)
    )
    sigma_param = pyro.param(
        "sigma_param", tensor(1.), constraint=constraints.positive
    )
    return pyro.sample("mu", dist.Delta(mu_param)), pyro.sample("sigma", dist.Delta(sigma_param))


conditioned = pyro.condition(model, data={"height": tensor(howell2['height'])})

pyro.clear_param_store()
svi = pyro.infer.SVI(
    model=conditioned,
    guide=guide,
    optim=pyro.optim.SGD({"lr": 0.001, "momentum": 0.1}),
    loss=pyro.infer.Trace_ELBO(),
)


guide = pyro.infer.autoguide.AutoLaplaceApproximation(conditioned)
laplace_guide = guide.laplace_approximation()
pred = pyro.infer.Predictive(laplace_guide, num_samples=1000)

it looks like you’re training your custom guide but not the laplace guide. the laplace guide is a replacement for the custom guide

1 Like

Thanks a lot! I totally was missing the point. Appreciate your help and patience.