Getting started in Ask-Tell Mode (Python)
The ask-tell interface in Dragonfly enables step-by-step optimization by directly exposing the next point to be evaluated in an iteration of Bayesian optimization.
Two main components are required in this interface: a function caller and an optimizer.
There are two different types of function callers: EuclideanFunctionCaller
and
CPFunctionCaller
. If the domain is limited to Euclidean spaces, use a
EuclideanFunctionCaller
, otherwise use a CPFunctionCaller
. For
Cartesian product spaces, you may also need to define orderings for the domain, which
can be passed in with the domain_orderings
argument in CPFunctionCaller
. It is important
to note that no objective function is passed in to the function caller. See the example
below for more details.
There are three different optimizers, similar to how the main API allows specification of
the optimization method using the opt_method
argument. In this interface, the optimizer
is explicitly created via <domain>GPBandit
, <domain>GAOptimiser
, or
<domain>RandomOptimiser
, where <domain>
is replaced by Euclidean
or CP
depending on
the domain used. This domain should be consistent with the function caller created. Here,
ask_tell_mode
should be set to True
to activate the ask-tell interface.
Finally, call initialise()
on the created optimizer to begin using the interface.
You can import the necessary components in python code via,
from dragonfly.exd import domains
from dragonfly.exd.experiment_caller import CPFunctionCaller, EuclideanFunctionCaller
from dragonfly.opt import random_optimiser, cp_ga_optimiser, gp_bandit
max_capital = 100
objective = lambda x: x[0] ** 4 - x[0]**2 + 0.1 * x[0]
domain = domains.EuclideanDomain([[-10, 10]])
func_caller = EuclideanFunctionCaller(None, domain)
opt = gp_bandit.EuclideanGPBandit(func_caller, ask_tell_mode=True)
opt.initialise()
for i in range(max_capital):
x = opt.ask()
y = objective(x)
print("x:", x, ", y:", y)
opt.tell([(x, y)])
Here, objective
is the function to be maximised,
domain
is the domain over which objective
is to be optimised,
and max_capital
is the capital available for optimisation.
In this interface, max_capital
is simply the maximum number of evaluations
to objective
.
To minimise the function, simply take the negative of the objective and perform the same procedure above.
ask
returns the next point to be evaluated in a numpy array. Once the point
is evaluated by calling the objective
function, tell
the point back to the
optimiser. Note that tell
takes one argument, where x
and y
are organized
into a tuple wrapped by a list.
As with the main API, the domain can be specified via a JSON file or in code. See the following example for more details. You can run it via, for example,
$ python examples/detailed_use_cases/in_code_demo_ask_tell.py
Multifidelity optimisation
The flow for multifidelity optimisation is very similar. In addition to the required components
mentioned above, a fidelity space and a fidelity value to optimise on is required as well. When
the objective is evaluated on both the fidelity coordinate z
and the domain coordinate x
,
the fidelity argument must also be specified by calling opt.tell([z, x, y])
.