Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

U(1,1) is zero, singular U with GP Kernel Prior #1863

Closed
joeddav opened this issue May 10, 2019 · 4 comments

Comments

@joeddav
Copy link

commented May 10, 2019

Issue Description

I'm trying to sample a GP regressor prior distribution placed over the length scale of the RBF kernel, just like is done in this example (see code sample below): http://docs.pyro.ai/en/stable/contrib.gp.html#pyro.contrib.gp.models.model.GPModel

However, I'm repeatedly running into the following error during sampling:

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

Depending on what parameters I choose for the prior distribution, this can happen part-way through sampling or it can happen during the very first sampling attempt. It seems to happen pretty consistently, however, across a variety of different prior distribution specifications.

I've been looking around the documentation, but don't see any obvious workaround such as a way to add a small constant to the potential energy or to allow the sampler to handle exceptions gracefully. Is there something I'm missing?

Environment

  • macOS Mojave version 10.14.2
  • Python 3.6
  • PyTorch 1.1.0
  • Pyro 0.3.3

Code Snippet

X1, y1 = make_regression(n_samples=10, n_features=3, n_informative=3, noise=.2)
... # standardize data, wrap in tensors
kernel = gp.kernels.RBF(input_dim=X1.shape[1])
kernel.set_prior("variance", dist.Uniform(torch.tensor(0.5), torch.tensor(1.5)))
kernel.set_prior("lengthscale", dist.Gamma(torch.tensor(7.5), torch.tensor(1.)))

gpr = gp.models.GPRegression(X1, y1, kernel, noise=torch.tensor(.01))

hmc_kernel = mcmc.HMC(gpr.model)
mcmc_run = mcmc.MCMC(hmc_kernel, num_samples=200)
posterior_ls_trace = []  # store lengthscale trace
ls_name = "GPR/RBF/lengthscale"
for trace, _ in mcmc_run._traces(): # exception raised here while sampling, before entering loop
    posterior_ls_trace.append(trace.nodes[ls_name]["value"].item())
@fehiepsi

This comment has been minimized.

Copy link
Collaborator

commented May 10, 2019

Thank you so much for a very clear bug explanation and code snippet! I'll look into this to see where is the problem.

@fehiepsi fehiepsi added the bug label May 10, 2019

@fehiepsi

This comment has been minimized.

Copy link
Collaborator

commented May 10, 2019

@joeddav The error happens at the warmup phase (before enter the loop). It turns out that we have to force lengthscale not take so small values. In GP, small lengthscale means that nearby points vary a lot, which in turn results with a singular kernel. We have to set a prior for lengthscale such as it is strictly positive. To force it strictly positive, one way is to use Truncated Distribution but it is not available yet in Pyro/PyTorch. Another way is to apply a linear transform to the prior, for example,

kernel.set_prior("lengthscale", dist.TransformedDistribution(
    dist.Gamma(torch.tensor(7.5), torch.tensor(1.)),
    [AffineTransform(loc=1, scale=1)]))

Let me know if it solves your issue. :)

@fehiepsi fehiepsi removed the bug label May 10, 2019

@fehiepsi

This comment has been minimized.

Copy link
Collaborator

commented May 10, 2019

Another solution is to ask PyTorch folks not trigger ValueError when applies Cholesky to singular matrix, but returns nan instead. So HMC/NUTS will be able to keep running when it gets nan (or diverging) during warmup phase). But in my opinion, using truncated distributions or transformed distributions as above are better solutions. ^^ I can implement TruncatedCauchy to make it easy for setting priors for strictly positive parameters if you want. (please open a FR in that case)

@fehiepsi

This comment has been minimized.

Copy link
Collaborator

commented May 20, 2019

I am going to close this issue. @joeddav Please feel free to open it again if the above solution does not work. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.