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

Add support for returning default configurations of CCS and ConfigSpace #2

Merged
merged 2 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 30 additions & 20 deletions skopt/optimizer/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,35 @@ def copy(self, random_state=None):

return optimizer

def _lie_to_optimizer(self, opt, strategy, x):
ti_available = "ps" in self.acq_func and len(opt.yi) > 0
ti = [t for (_, t) in opt.yi] if ti_available else None
if strategy == "cl_min":
y_lie = np.min(opt.yi) if opt.yi else 0.0 # CL-min lie
t_lie = np.min(ti) if ti is not None else log(sys.float_info.max)
elif strategy == "cl_mean":
y_lie = np.mean(opt.yi) if opt.yi else 0.0 # CL-mean lie
t_lie = np.mean(ti) if ti is not None else log(sys.float_info.max)
else:
y_lie = np.max(opt.yi) if opt.yi else 0.0 # CL-max lie
t_lie = np.max(ti) if ti is not None else log(sys.float_info.max)

# Lie to the optimizer.
if "ps" in self.acq_func:
# Use `_tell()` instead of `tell()` to prevent repeated
# log transformations of the computation times.
opt._tell(x, (y_lie, t_lie))
else:
opt._tell(x, y_lie)

def ask_default(self, strategy="cl_min"):
x = self.space.default()
if x is not None:
self.sampled.append(x)
opt = self.copy(random_state=self.rng.randint(0, np.iinfo(np.int32).max))
self._lie_to_optimizer(opt, strategy, x)
return x

def ask(self, n_points=None, strategy="cl_min"):
"""Query point or multiple points at which objective should be evaluated.

Expand Down Expand Up @@ -463,26 +492,7 @@ def ask(self, n_points=None, strategy="cl_min"):
if i == n_points - 1:
break

ti_available = "ps" in self.acq_func and len(opt.yi) > 0
ti = [t for (_, t) in opt.yi] if ti_available else None

if strategy == "cl_min":
y_lie = np.min(opt.yi) if opt.yi else 0.0 # CL-min lie
t_lie = np.min(ti) if ti is not None else log(sys.float_info.max)
elif strategy == "cl_mean":
y_lie = np.mean(opt.yi) if opt.yi else 0.0 # CL-mean lie
t_lie = np.mean(ti) if ti is not None else log(sys.float_info.max)
else:
y_lie = np.max(opt.yi) if opt.yi else 0.0 # CL-max lie
t_lie = np.max(ti) if ti is not None else log(sys.float_info.max)

# Lie to the optimizer.
if "ps" in self.acq_func:
# Use `_tell()` instead of `tell()` to prevent repeated
# log transformations of the computation times.
opt._tell(x, (y_lie, t_lie))
else:
opt._tell(x, y_lie)
self._lie_to_optimizer(opt, strategy, x)

self.cache_ = {(n_points, strategy): X} # cache_ the result

Expand Down
78 changes: 49 additions & 29 deletions skopt/space/space.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,9 +673,12 @@ def __contains__(self, point):
@property
def transformed_bounds(self):
if self.transform_ == "normalize":
return 0., 1.
return 0.0, 1.0
else:
return (self.low, self.high)
if self.prior == "uniform":
return self.low, self.high
else:
return np.log10(self.low), np.log10(self.high)

def distance(self, a, b):
"""Compute distance between point `a` and `b`.
Expand Down Expand Up @@ -1118,6 +1121,43 @@ def from_yaml(cls, yml_path, namespace=None):

return space

def _cs_post_process_conf(self, hps_names, conf):
point = []
for hp_name in hps_names:
val = np.nan
if self.hps_type[hp_name] == "Categorical":
val = "NA"
if hp_name in conf.keys():
val = conf[hp_name]
point.append(val)
return point


def _ccs_post_process_conf(self, hps_names, conf):
point = []
values = conf.values
for i, hp_name in enumerate(hps_names):
val = values[i]
if CCS.ccs_inactive == val:
if self.hps_type[hp_name] == "Categorical":
val = "NA"
else:
val = np.nan
point.append(val)
return point

def default(self):
if self.is_config_space:
conf = self.config_space.get_default_configuration()
hps_names = self.config_space.get_hyperparameter_names()
return self._cs_post_process_conf(hps_names, conf)
elif self.is_ccs:
conf = self.ccs.default_configuration
hps_names = [x.name for x in self.ccs.hyperparameters]
return self._ccs_post_process_conf(hps_names, conf)
else:
return None

def rvs(self, n_samples=1, random_state=None):
"""Draw random samples.

Expand All @@ -1140,42 +1180,22 @@ def rvs(self, n_samples=1, random_state=None):
"""
rng = check_random_state(random_state)
if self.is_config_space:
req_points = []

points = []
confs = self.config_space.sample_configuration(n_samples)
if n_samples == 1:
confs = [confs]

hps_names = self.config_space.get_hyperparameter_names()
for conf in confs:
point = []
for hps_name in hps_names:
val = np.nan
if self.hps_type[hps_name] == "Categorical":
val = "NA"
if hps_name in conf.keys():
val = conf[hps_name]
point.append(val)
req_points.append(point)

return req_points
point = self._cs_post_process_conf(hps_names, conf)
points.append(point)
return points
elif self.is_ccs:
confs = self.ccs.samples(n_samples)
hps = self.ccs.hyperparameters
points = []
confs = self.ccs.samples(n_samples)
hps_names = [x.name for x in self.ccs.hyperparameters]
for conf in confs:
point = []
values = conf.values
for i, hp in enumerate(hps):
val = values[i]
if CCS.ccs_inactive == val:
if self.hps_type[hp.name] == "Categorical":
val = "NA"
else:
val = np.nan
point.append(val)
point = self._ccs_post_process_conf(hps_names, conf)
points.append(point)

return points
else:
# Draw
Expand Down