Closed yyexela closed 1 year ago
Why is it that the lengthscale being found is sometimes so small? (it also gets very big but this doesn't cause issues)
Good question. A fundamental difference between fit_gpytorch_mll
and the standard gpytorch fitting loop is that fit_gpytorch_mll
by default uses L-BFGS to fit the model. So it's not a standard first-order gradient descent method that with limited learning rate will behave rather docile - instead it can run off to very large (and numerically problematic) values - especially since there aren't priors and/or constraints on many of the model parameters. We'd have to take a closer look what exactly is going on there (not ruling out a bug in your [or our] code, but haven't looked through this in complete detail).
Why, when I add the lengthscale constraint, does fit_gpytorch_mll bounce between my bounds?
This is intriguing. It could be that the MLL is multi-modal and both of the extreme value solutions can (in conjunction with the other parameters) explain the data well (or at least better than other solutions on the interior).
@j-wilson, @dme65 any other thoughts / intuition on this?
@yyexela I don't see an obvious reason why this is happening. It may simply be a model initialization issue (as Max suggested). I recommend visualizing 1-2 dimensional loss landscapes to help diagnose. The problem seems to go away upon standardizing the outcome values in run_BO_loop
as:
for i in range(BO_iters):
print(f"<------ BO iteration {i+1} of {BO_iters} ------>")
train_Y = (init_Y - init_Y.mean())/init_Y.std()
mll, model = initialize_model(init_X, train_Y)
train_model(model, mll, init_X, train_Y)
cd = get_candidate(model, init_X)
...
p.s. You may also want to consider using ARD lengthscales.
Thanks @j-wilson and @Balandat ! Normalizing my training data fixed the issue.
🐛 Bug
When training a simple, custom GPyTorch model, sometimes the length-scale of the kernel is incredibly small (smaller than the order of
1e-100
). Then, calculating the Cholesky decomposition fails and thesymeig method
is used. Sometimes, this doesn't cause anything to break, but other times there are extremely negative eigenvalues. This then causes a run time error later down the line in optimizing the qNEI acquisition function because someNaN
values are produced. Adding a constraint on the lengthscale of the kernel resolves the issue, but instead I'm seeing that the lengthscale after optimization withfit_gpytorch_mll
bounces back and forth between my bounds (1e-3 to 1e3) most of the time.I'm considering this a
BoTorch
bug since it only occurs when usingfit_gpytorch_mll
. When I use GPyTorch fitting only (viause_gpytorch_fit_only = True
in my code below), the lengthscales are reasonable values.So, I have two concerns with
fit_gpytorch_mll
: 1) Why is it that the lengthscale being found is sometimes so small? (it also gets very big but this doesn't cause issues) 2) Why, when I add the lengthscale constraint, doesfit_gpytorch_mll
bounce between my bounds?In the below code, running with
reproduces this error and
fixes it.
Code snippet to reproduce
Stack trace/error message (Note: the failure depends on the seed and version of packages used, after updating all my packages it failed on iteration 49, so try a different seed if you didn't encounter the error)
Expected Behavior
I expect to be able to obtain a candidate value from the qNEI acquisition function and continue iterating through my BO loop. Something like this:
System information
Please complete the following information:
Additional context
I ran into this issue when comparing derivative enabled GPs with non-derivative enabled ones. The derivative enabled GP doesn't run into the
NaN
issue even though sometimes its lengthscales are exaggerated as well.Also, see here for a relevant
TODO
I found as well. I found it when debugging the covariance matrix and seeing a very negative eigenvalue for what should be at minimum a positive semi definite matrix.