josejimenezluna / pyGPGO

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

Passing parameter arrays #30

Closed jdmoore7 closed 3 years ago

jdmoore7 commented 3 years ago

Not seeing a way in documentation to easily pass arrays into PyGPGO. The hackiest way I've thought of handling this problem is as follows:

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

param = {f'x_{i}': ('cont', [0, 1]) for i in range(3)}
param.update({f'y_{i}': ('cont', [0, 1]) for i in range(3)})

def f(p):
    v1 = np.array([p[f'x_{i}'] for i in range(3)])
    v2 = np.array([p[f'y_{i}'] for i in range(3)])
    return np.dot(v1,v2)

sexp = squaredExponential()
gp = GaussianProcess(sexp)
acq = Acquisition(mode='ExpectedImprovement')

np.random.seed(23)
gpgo = GPGO(gp, acq, f, param)
gpgo.run(max_iter=20)

However, the error is returned:

Evaluation   Proposed point       Current eval.      Best eval.
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-49-f58f602dca8c> in <module>()
     26 np.random.seed(23)
     27 gpgo = GPGO(gp, acq, f, param)
---> 28 gpgo.run(max_iter=20)

1 frames
/usr/local/lib/python3.7/dist-packages/pyGPGO/GPGO.py in _firstRun(self, n_eval)
     86             s_param_val = list(s_param.values())
     87             self.X[i] = s_param_val
---> 88             self.y[i] = self.f(**s_param)
     89         self.GP.fit(self.X, self.y)
     90         self.tau = np.max(self.y)

TypeError: f() got an unexpected keyword argument 'x_1'
josejimenezluna commented 3 years ago

Hi @jdmoore7 , you can probably use kwargs in the function definition to achieve the desired result:

def f(**kwargs):
    v1 = np.array([kwargs[f'x_{i}'] for i in range(2)])
    v2 = np.array([kwargs[f'y_{i}'] for i in range(2)])
    return np.dot(v1, v2)

Let me know if this helps.

jdmoore7 commented 3 years ago

Perfect fix, thanks!