Skip to content

Commit

Permalink
Fix differential evolution
Browse files Browse the repository at this point in the history
  • Loading branch information
hadarshavit committed Oct 9, 2024
1 parent 9d19475 commit 8dc463f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 59 deletions.
10 changes: 7 additions & 3 deletions smac/acquisition/maximizer/differential_evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from scipy.optimize._differentialevolution import DifferentialEvolutionSolver

from smac.acquisition.maximizer import AbstractAcquisitionMaximizer
from smac.utils.configspace import transform_continuous_designs

__copyright__ = "Copyright 2022, automl.org"
__license__ = "3-clause BSD"
Expand Down Expand Up @@ -36,7 +37,9 @@ def _maximize(

def func(x: np.ndarray) -> np.ndarray:
assert self._acquisition_function is not None
return -self._acquisition_function([Configuration(self._configspace, vector=x)])
return -self._acquisition_function([transform_continuous_designs(
design=np.expand_dims(x, axis=0), origin="Diffrential Evolution", configspace=self._configspace
)[0]])

ds = DifferentialEvolutionSolver(
func,
Expand All @@ -58,8 +61,9 @@ def func(x: np.ndarray) -> np.ndarray:

_ = ds.solve()
for pop, val in zip(ds.population, ds.population_energies):
rc = Configuration(self._configspace, vector=pop)
rc.origin = "Acquisition Function Maximizer: Differential Evolution"
rc = transform_continuous_designs(
design=np.expand_dims(pop, axis=0), origin="Acquisition Function Maximizer: Differential Evolution", configspace=self._configspace
)[0]
configs.append((-val, rc))

configs.sort(key=lambda t: t[0])
Expand Down
54 changes: 0 additions & 54 deletions smac/initial_design/abstract_initial_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,57 +155,3 @@ def select_configurations(self) -> list[Configuration]:
def _select_configurations(self) -> list[Configuration]:
"""Selects the initial configurations, depending on the implementation of the initial design."""
raise NotImplementedError

def _transform_continuous_designs(
self, design: np.ndarray, origin: str, configspace: ConfigurationSpace
) -> list[Configuration]:
"""Transforms the continuous designs into a discrete list of configurations.
Parameters
----------
design : np.ndarray
Array of hyperparameters originating from the initial design strategy.
origin : str | None, defaults to None
Label for a configuration where it originated from.
configspace : ConfigurationSpace
Returns
-------
configs : list[Configuration]
Continuous transformed configs.
"""
params = configspace.get_hyperparameters()
for idx, param in enumerate(params):
if isinstance(param, IntegerHyperparameter):
design[:, idx] = param._inverse_transform(param._transform(design[:, idx]))
elif isinstance(param, NumericalHyperparameter):
continue
elif isinstance(param, Constant):
design_ = np.zeros(np.array(design.shape) + np.array((0, 1)))
design_[:, :idx] = design[:, :idx]
design_[:, idx + 1 :] = design[:, idx:]
design = design_
elif isinstance(param, CategoricalHyperparameter):
v_design = design[:, idx]
v_design[v_design == 1] = 1 - 10**-10
design[:, idx] = np.array(v_design * len(param.choices), dtype=int)
elif isinstance(param, OrdinalHyperparameter):
v_design = design[:, idx]
v_design[v_design == 1] = 1 - 10**-10
design[:, idx] = np.array(v_design * len(param.sequence), dtype=int)
else:
raise ValueError("Hyperparameter not supported when transforming a continuous design.")

configs = []
for vector in design:
try:
conf = deactivate_inactive_hyperparameters(
configuration=None, configuration_space=configspace, vector=vector
)
except ForbiddenValueError:
continue

conf.origin = origin
configs.append(conf)

return configs
3 changes: 2 additions & 1 deletion smac/initial_design/latin_hypercube_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from scipy.stats.qmc import LatinHypercube

from smac.initial_design.abstract_initial_design import AbstractInitialDesign
from smac.utils.configspace import transform_continuous_designs

__copyright__ = "Copyright 2022, automl.org"
__license__ = "3-clause BSD"
Expand All @@ -25,6 +26,6 @@ def _select_configurations(self) -> list[Configuration]:

lhd = LatinHypercube(d=len(params) - constants, seed=self._rng.randint(0, 1000000)).random(n=self._n_configs)

return self._transform_continuous_designs(
return transform_continuous_designs(
design=lhd, origin="Initial Design: Latin Hypercube", configspace=self._configspace
)
4 changes: 3 additions & 1 deletion smac/initial_design/sobol_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from scipy.stats.qmc import Sobol

from smac.initial_design.abstract_initial_design import AbstractInitialDesign
from smac.utils.configspace import transform_continuous_designs


__copyright__ = "Copyright 2022, automl.org"
__license__ = "3-clause BSD"
Expand Down Expand Up @@ -43,6 +45,6 @@ def _select_configurations(self) -> list[Configuration]:
warnings.simplefilter("ignore")
sobol = sobol_gen.random(self._n_configs)

return self._transform_continuous_designs(
return transform_continuous_designs(
design=sobol, origin="Initial Design: Sobol", configspace=self._configspace
)
58 changes: 58 additions & 0 deletions smac/utils/configspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
OrdinalHyperparameter,
UniformFloatHyperparameter,
UniformIntegerHyperparameter,
IntegerHyperparameter,
NumericalHyperparameter,
)
from ConfigSpace.util import ForbiddenValueError, deactivate_inactive_hyperparameters
from ConfigSpace.util import get_one_exchange_neighbourhood

__copyright__ = "Copyright 2022, automl.org"
Expand Down Expand Up @@ -182,6 +185,61 @@ def print_config_changes(
logger.debug(msg)


def transform_continuous_designs(
design: np.ndarray, origin: str, configspace: ConfigurationSpace
) -> list[Configuration]:
"""Transforms the continuous designs into a discrete list of configurations.
Parameters
----------
design : np.ndarray
Array of hyperparameters originating from the initial design strategy.
origin : str | None, defaults to None
Label for a configuration where it originated from.
configspace : ConfigurationSpace
Returns
-------
configs : list[Configuration]
Continuous transformed configs.
"""
params = configspace.get_hyperparameters()
for idx, param in enumerate(params):
if isinstance(param, IntegerHyperparameter):
design[:, idx] = param._inverse_transform(param._transform(design[:, idx]))
elif isinstance(param, NumericalHyperparameter):
continue
elif isinstance(param, Constant):
design_ = np.zeros(np.array(design.shape) + np.array((0, 1)))
design_[:, :idx] = design[:, :idx]
design_[:, idx + 1 :] = design[:, idx:]
design = design_
elif isinstance(param, CategoricalHyperparameter):
v_design = design[:, idx]
v_design[v_design == 1] = 1 - 10**-10
design[:, idx] = np.array(v_design * len(param.choices), dtype=int)
elif isinstance(param, OrdinalHyperparameter):
v_design = design[:, idx]
v_design[v_design == 1] = 1 - 10**-10
design[:, idx] = np.array(v_design * len(param.sequence), dtype=int)
else:
raise ValueError("Hyperparameter not supported when transforming a continuous design.")

configs = []
for vector in design:
try:
conf = deactivate_inactive_hyperparameters(
configuration=None, configuration_space=configspace, vector=vector
)
except ForbiddenValueError:
continue

conf.origin = origin
configs.append(conf)

return configs


# def check_subspace_points(
# X: np.ndarray,
# cont_dims: np.ndarray | list = [],
Expand Down

0 comments on commit 8dc463f

Please sign in to comment.