import os
import warnings
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import bofire.strategies.api as strategies
from bofire.benchmarks.api import Branin
from bofire.data_models.acquisition_functions.api import qEI
from bofire.data_models.domain.api import Domain
from bofire.data_models.strategies.api import (
LSRBO,
BotorchOptimizer,
RandomStrategy,
SoboStrategy,
)
from bofire.runners.api import run
warnings.filterwarnings("ignore")
bench = Branin(locality_factor=0.5)
def sample(domain):
sampled = domain.inputs.sample(10)
return sampled
# sampled = bench.f(sampled, return_complete = True)
# sampled = sampled.sort_values(by="y", ascending=False, ignore_index=True)
# return sampled[bench.domain.inputs.get_keys()].copy()
def best(domain: Domain, experiments: pd.DataFrame) -> float:
return experiments.y.min()
SMOKE_TEST = os.environ.get("SMOKE_TEST")Local Search Region Bayesian Optimization
In this notebook the Branin benchmark from paper about local search region BO (https://www.merl.com/publications/docs/TR2023-057.pdf) is reproduced. Note that we use here by purpose qEI as acquisition function to reproduce the paper.
Imports and helper methods
Random Optimization
Here random sampling is performed without any local search region constraints applied.
random_results = [
run(
Branin(locality_factor=0.5),
strategy_factory=lambda domain: strategies.map(RandomStrategy(domain=domain)),
n_iterations=80 if not SMOKE_TEST else 1,
metric=best,
initial_sampler=sample,
n_runs=1,
n_procs=1,
)
for _ in range(5 if not SMOKE_TEST else 1)
] 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s, Current Best:=5.967]Run 0: 100%|██████████| 1/1 [00:00<00:00, 94.22it/s, Current Best:=5.967]
SOBO Optimization
Here standard bayesian optimization is performed without any local search region constraints applied using the qEI acquistion function.
sobo_results = [
run(
Branin(locality_factor=0.5),
strategy_factory=lambda domain: strategies.map(
SoboStrategy(domain=domain, acquisition_function=qEI()),
),
n_iterations=80 if not SMOKE_TEST else 1,
metric=best,
initial_sampler=sample,
n_runs=1,
n_procs=1,
)
for _ in range(5 if not SMOKE_TEST else 1)
] 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s, Current Best:=4.689]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.75it/s, Current Best:=4.689]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.75it/s, Current Best:=4.689]
Local SOBO Optimization
Here bayesian optimization is performed with setting gamma parameter of the LSR-BO method to 0 which results in a pure local optimization with respect to the last random sample.
local_results = [
run(
Branin(locality_factor=0.5),
strategy_factory=lambda domain: strategies.map(
SoboStrategy(
domain=domain,
acquisition_function=qEI(),
acquisition_optimizer=BotorchOptimizer(
local_search_config=LSRBO(gamma=0)
),
),
),
n_iterations=80 if not SMOKE_TEST else 1,
metric=best,
initial_sampler=sample,
n_runs=1,
n_procs=1,
)
for _ in range(5 if not SMOKE_TEST else 1)
] 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s, Current Best:=3.726]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.42it/s, Current Best:=3.726]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.41it/s, Current Best:=3.726]
Global SOBO Optimization (Projection)
Here bayesian optimization is performed with setting gamma parameter of the LSR-BO method to 500 which results in taking always the biggest step in the direction of the global candidate. In the original paper, this is called “Projection”.
global_results = [
run(
Branin(locality_factor=0.5),
strategy_factory=lambda domain: strategies.map(
SoboStrategy(
domain=domain,
acquisition_function=qEI(),
acquisition_optimizer=BotorchOptimizer(
local_search_config=LSRBO(gamma=500)
),
),
),
n_iterations=80 if not SMOKE_TEST else 1,
metric=best,
initial_sampler=sample,
n_runs=1,
n_procs=1,
)
for _ in range(5 if not SMOKE_TEST else 1)
] 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s, Current Best:=8.800]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.62it/s, Current Best:=8.800]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.61it/s, Current Best:=8.800]
LSR-BO
Here the actual method from the paper is performed with setting gamma to 0.1.
lsr_results = [
run(
Branin(locality_factor=0.5),
strategy_factory=lambda domain: strategies.map(
SoboStrategy(
domain=domain,
acquisition_function=qEI(),
acquisition_optimizer=BotorchOptimizer(
local_search_config=LSRBO(gamma=0.1)
),
),
),
n_iterations=80 if not SMOKE_TEST else 1,
metric=best,
initial_sampler=sample,
n_runs=1,
n_procs=1,
)
for _ in range(5 if not SMOKE_TEST else 1)
] 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s]Run 0: 0%| | 0/1 [00:00<?, ?it/s, Current Best:=6.514]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.45it/s, Current Best:=6.514]Run 0: 100%|██████████| 1/1 [00:00<00:00, 2.45it/s, Current Best:=6.514]
Plot the results
if not SMOKE_TEST:
fig, ax = plt.subplots()
best_random = np.array(
[random_results[i][0][1] for i in range(len(random_results))]
)
ax.plot(range(80), best_random.mean(axis=0), color="gray", label="Random")
ax.fill_between(
range(80),
(best_random.mean(0) - best_random.std(0)),
(best_random.mean(0) + best_random.std(0)),
alpha=0.3,
color="gray",
)
best_global = np.log10(
np.array([global_results[i][0][1] for i in range(len(global_results))])
- 0.397887,
)
ax.plot(range(80), best_global.mean(axis=0), color="orange", label="Projection")
ax.fill_between(
range(80),
(best_global.mean(0) - best_global.std(0)),
(best_global.mean(0) + best_global.std(0)),
alpha=0.3,
color="orange",
)
best_local = np.log10(
np.array([local_results[i][0][1] for i in range(len(global_results))])
- 0.397887,
)
ax.plot(range(80), best_local.mean(axis=0), color="green", label="Local")
ax.fill_between(
range(80),
(best_local.mean(0) - best_local.std(0)),
(best_local.mean(0) + best_local.std(0)),
alpha=0.3,
color="green",
)
best_lsr = np.log10(
np.array([lsr_results[i][0][1] for i in range(len(lsr_results))]) - 0.397887,
)
ax.plot(range(80), best_lsr.mean(axis=0), color="blue", label="LSR")
ax.fill_between(
range(80),
(best_lsr.mean(0) - best_lsr.std(0)),
(best_lsr.mean(0) + best_lsr.std(0)),
alpha=0.3,
color="blue",
)
best_unconstrained = np.log10(
np.array([sobo_results[i][0][1] for i in range(len(sobo_results))]) - 0.397887,
)
ax.plot(
range(80), best_unconstrained.mean(axis=0), color="red", label="Unconstrained"
)
ax.fill_between(
range(80),
(best_unconstrained.mean(0) - best_unconstrained.std(0)),
(best_unconstrained.mean(0) + best_unconstrained.std(0)),
alpha=0.3,
color="red",
)
ax.set_xlabel("Iteration")
ax.set_ylabel("Log10(SimpleRegret)")
ax.legend()
plt.show()