Note
Go to the end to download the full example code. or to run this example in your browser via Binder
Ask-and-Tell¶
This examples show how to use the Ask-and-Tell interface.
[INFO][abstract_initial_design.py:147] Using 20 initial design configurations and 0 additional configurations.
[INFO][abstract_intensifier.py:516] Added config 73bd77 as new incumbent because there are no incumbents yet.
[INFO][abstract_intensifier.py:595] Added config 1a3757 and rejected config 73bd77 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config 0c7ad4 and rejected config 1a3757 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config 8ee2dd and rejected config 0c7ad4 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config cd8a03 and rejected config 8ee2dd as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config 8554e9 and rejected config cd8a03 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][smbo.py:320] Finished 50 trials.
[INFO][abstract_intensifier.py:595] Added config 636d32 and rejected config 8554e9 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config dd7491 and rejected config 636d32 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config d1c9ea and rejected config dd7491 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config b888c4 and rejected config d1c9ea as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config 858410 and rejected config b888c4 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config dda40a and rejected config 858410 as incumbent because it is not better than the incumbents on 1 instances:
[INFO][abstract_intensifier.py:595] Added config d5a193 and rejected config dda40a as incumbent because it is not better than the incumbents on 1 instances:
[INFO][smbo.py:320] Finished 100 trials.
[INFO][smbo.py:328] Configuration budget is exhausted:
[INFO][smbo.py:329] --- Remaining wallclock time: inf
[INFO][smbo.py:330] --- Remaining cpu time: inf
[INFO][smbo.py:331] --- Remaining trials: 0
Default cost: 16916.0
Incumbent cost: 0.6260486651666125
from ConfigSpace import Configuration, ConfigurationSpace, Float
from smac import HyperparameterOptimizationFacade, Scenario
from smac.runhistory.dataclasses import TrialValue
__copyright__ = "Copyright 2021, AutoML.org Freiburg-Hannover"
__license__ = "3-clause BSD"
class Rosenbrock2D:
@property
def configspace(self) -> ConfigurationSpace:
cs = ConfigurationSpace(seed=0)
x0 = Float("x0", (-5, 10), default=-3)
x1 = Float("x1", (-5, 10), default=-4)
cs.add([x0, x1])
return cs
def train(self, config: Configuration, seed: int = 0) -> float:
"""The 2-dimensional Rosenbrock function as a toy model.
The Rosenbrock function is well know in the optimization community and
often serves as a toy problem. It can be defined for arbitrary
dimensions. The minimium is always at x_i = 1 with a function value of
zero. All input parameters are continuous. The search domain for
all x's is the interval [-5, 10].
"""
x1 = config["x0"]
x2 = config["x1"]
cost = 100.0 * (x2 - x1**2.0) ** 2.0 + (1 - x1) ** 2.0
return cost
if __name__ == "__main__":
model = Rosenbrock2D()
# Scenario object
scenario = Scenario(model.configspace, deterministic=False, n_trials=100)
intensifier = HyperparameterOptimizationFacade.get_intensifier(
scenario,
max_config_calls=1, # We basically use one seed per config only
)
# Now we use SMAC to find the best hyperparameters
smac = HyperparameterOptimizationFacade(
scenario,
model.train,
intensifier=intensifier,
overwrite=True,
)
# We can ask SMAC which trials should be evaluated next
for _ in range(10):
info = smac.ask()
assert info.seed is not None
cost = model.train(info.config, seed=info.seed)
value = TrialValue(cost=cost, time=0.5)
smac.tell(info, value)
# After calling ask+tell, we can still optimize
# Note: SMAC will optimize the next 90 trials because 10 trials already have been evaluated
incumbent = smac.optimize()
# Get cost of default configuration
default_cost = smac.validate(model.configspace.get_default_configuration())
print(f"Default cost: {default_cost}")
# Let's calculate the cost of the incumbent
incumbent_cost = smac.validate(incumbent)
print(f"Incumbent cost: {incumbent_cost}")
Total running time of the script: (0 minutes 3.936 seconds)