josejimenezluna / pyGPGO

Bayesian optimization for Python
http://pygpgo.readthedocs.io
MIT License
241 stars 62 forks source link

GP.fit() error when K not PD #23

Open RemiDav opened 5 years ago

RemiDav commented 5 years ago

I have an issue with GP.fit() when self.covfunc.K(self.X, self.X) returns a K that is not positive definite.

I am suspecting that it happens when the same gpgo.best is selected several times in a row, but I am not sure. Is there a way to handle this ?

Traceback:

 File "<ipython-input-219-e67b7c4ee454>", line 20, in <module>
    gpgo.updateGP()

  File "C:\ProgramData\Anaconda3\lib\site-packages\pyGPGO\GPGO.py", line 150, in updateGP
    self.GP.update(np.atleast_2d(self.best), np.atleast_1d(f_new))

  File "C:\ProgramData\Anaconda3\lib\site-packages\pyGPGO\surrogates\GaussianProcess.py", line 241, in update
    self.fit(X, y)

  File "C:\ProgramData\Anaconda3\lib\site-packages\pyGPGO\surrogates\GaussianProcess.py", line 78, in fit
    self.L = cholesky(self.K).T

  File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\linalg\decomp_cholesky.py", line 91, in cholesky
    check_finite=check_finite)

  File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\linalg\decomp_cholesky.py", line 40, in _cholesky
    "definite" % info)

LinAlgError: 30-th leading minor of the array is not positive definite
josejimenezluna commented 5 years ago

Hello @RemiDav, could you provide a minimum working example so that I can replicate this behaviour?

RemiDav commented 5 years ago

I think the problems comes when the optimization returns the same point to evaluate several times in a row:

import numpy as np
from pyGPGO.covfunc import squaredExponential
from pyGPGO.acquisition import Acquisition
from pyGPGO.surrogates.GaussianProcess import GaussianProcess
from pyGPGO.GPGO import GPGO

def f(x):
    return (np.sin(x))

covfunc = squaredExponential()
gpr = GaussianProcess(covfunc)
acq = Acquisition(mode='ExpectedImprovement')
param = {'x': ('cont', [0, 2 * np.pi])}

gpgo_obj = GPGO(gpr, acq, f, param)
gpgo_obj.run(max_iter=1) #initialize

# run 6 evaluations at the same point
gpgo_obj.best = [0.]
gpgo_obj.updateGP()
gpgo_obj.updateGP()
gpgo_obj.updateGP()
gpgo_obj.updateGP()
gpgo_obj.updateGP()
gpgo_obj.updateGP()