Skip to content
This repository has been archived by the owner on Feb 28, 2024. It is now read-only.

Commit

Permalink
Group acquisition function and acquisition optimizer arguments (#298)
Browse files Browse the repository at this point in the history
  • Loading branch information
MechCoder authored and glouppe committed Jan 12, 2017
1 parent 1533d1e commit 1d9ddba
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 39 deletions.
13 changes: 9 additions & 4 deletions skopt/acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
from scipy.stats import norm


def gaussian_acquisition_1D(X, model, y_opt=None, acq_func="LCB", xi=0.01,
kappa=1.96):
def gaussian_acquisition_1D(X, model, y_opt=None, acq_func="LCB",
acq_func_kwargs=None):
"""
A wrapper around the acquisition function that is called by fmin_l_bfgs_b.
This is because lbfgs allows only 1-D input.
"""
return _gaussian_acquisition(np.expand_dims(X, axis=0),
model, y_opt, acq_func, xi, kappa,
model, y_opt, acq_func_kwargs=acq_func_kwargs,
return_grad=True)


def _gaussian_acquisition(X, model, y_opt=None, acq_func="LCB",
xi=0.01, kappa=1.96, return_grad=False):
return_grad=False, acq_func_kwargs=None):
"""
Wrapper so that the output of this function can be
directly passed to a minimizer.
Expand All @@ -27,6 +27,11 @@ def _gaussian_acquisition(X, model, y_opt=None, acq_func="LCB",
if X.ndim != 2:
raise ValueError("X should be 2-dimensional.")

if acq_func_kwargs is None:
acq_func_kwargs = dict()
xi = acq_func_kwargs.get("xi", 0.01)
kappa = acq_func_kwargs.get("kappa", 1.96)

# Evaluate acquisition function
if acq_func == "LCB":
return gaussian_lcb(X, model, kappa, return_grad)
Expand Down
10 changes: 8 additions & 2 deletions skopt/optimizer/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,15 @@ def base_minimize(func, dimensions, base_estimator,
specs = {"args": copy.copy(inspect.currentframe().f_locals),
"function": inspect.currentframe().f_code.co_name}

acq_optimizer_kwargs = {
"n_points": n_points, "n_restarts_optimizer": n_restarts_optimizer,
"n_jobs": n_jobs}
acq_func_kwargs = {"xi": xi, "kappa": kappa}

optimizer = Optimizer(dimensions, base_estimator, n_random_starts,
acq_func, acq_optimizer, random_state, n_points,
n_restarts_optimizer, xi, kappa, n_jobs)
acq_func, acq_optimizer, random_state,
acq_optimizer_kwargs=acq_optimizer_kwargs,
acq_func_kwargs=acq_func_kwargs)

# Initialize with provided points (x0 and y0) and/or random points
if x0 is None:
Expand Down
53 changes: 20 additions & 33 deletions skopt/optimizer/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,30 +74,11 @@ class Optimizer(object):
Set random state to something other than None for reproducible
results.
* `n_points` [int, default=500]:
Number of points to sample to determine the next "best" point.
Useless if acq_optimizer is set to `"lbfgs"`.
* `n_restarts_optimizer` [int, default=5]:
The number of restarts of the optimizer when `acq_optimizer`
is `"lbfgs"`.
* `xi` [float, default=0.01]:
Controls how much improvement one wants over the previous best
values. Used when the acquisition is either `"EI"` or `"PI"`.
* `kappa` [float, default=1.96]:
Controls how much of the variance in the predicted values should be
taken into account. If set to be very high, then we are favouring
exploration over exploitation and vice versa.
Used when the acquisition is `"LCB"`.
* `n_jobs` [int, default=1]
Number of cores to run in parallel while running the lbfgs
optimizations over the acquisition function. Valid only when
`acq_optimizer` is set to "lbfgs."
Defaults to 1 core. If `n_jobs=-1`, then number of jobs is set
to number of cores.
* `acq_func_kwargs` [dict]:
Additional arguments to be passed to the acquistion function.
* `acq_optimizer_kwargs` [dict]:
Additional arguments to be passed to the acquistion optimizer.
Attributes
----------
Expand All @@ -115,15 +96,21 @@ class Optimizer(object):
"""
def __init__(self, dimensions, base_estimator,
n_random_starts=10, acq_func="EI", acq_optimizer="lbfgs",
random_state=None, n_points=10000, n_restarts_optimizer=5,
xi=0.01, kappa=1.96, n_jobs=1):
random_state=None, acq_func_kwargs=None,
acq_optimizer_kwargs=None):
# Arguments that are just stored not checked
self.acq_func = acq_func
self.rng = check_random_state(random_state)
self.kappa = kappa
self.n_points = n_points
self.n_restarts_optimizer = n_restarts_optimizer
self.xi = xi
self.acq_func_kwargs = acq_func_kwargs

if acq_optimizer_kwargs is None:
acq_optimizer_kwargs = dict()

self.n_points = acq_optimizer_kwargs.get("n_points", 10000)
self.n_restarts_optimizer = acq_optimizer_kwargs.get(
"n_restarts_optimizer", 5)
n_jobs = acq_optimizer_kwargs.get("n_jobs", 1)

self.space = Space(dimensions)
self.models = []
self.Xi = []
Expand Down Expand Up @@ -222,8 +209,8 @@ def tell(self, x, y, fit=True):
X = self.space.transform(self.space.rvs(
n_samples=self.n_points, random_state=self.rng))
values = _gaussian_acquisition(
X=X, model=est, y_opt=np.min(self.yi),
acq_func=self.acq_func, xi=self.xi, kappa=self.kappa)
X=X, model=est, y_opt=np.min(self.yi),
acq_func=self.acq_func, acq_func_kwargs=self.acq_func_kwargs)

# Find the minimum of the acquisition function by randomly sampling
# points from the space
Expand All @@ -241,7 +228,7 @@ def tell(self, x, y, fit=True):
jobs = (delayed(fmin_l_bfgs_b)(
gaussian_acquisition_1D, x,
args=(est, np.min(self.yi), self.acq_func,
self.xi, self.kappa),
self.acq_func_kwargs),
bounds=self.space.transformed_bounds,
approx_grad=False,
maxiter=20) for x in x0)
Expand Down

0 comments on commit 1d9ddba

Please sign in to comment.