Hyperparameters¶
Consider the Booth test function (below). This function varies differently in different directions, and these directions are somewhat skewed with respect to the inputs. Our agent will automatically fit the right hyperparameters to account for this.
[1]:
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
from blop.utils import functions
x1 = x2 = np.linspace(-10, 10, 256)
X1, X2 = np.meshgrid(x1, x2)
F = functions.booth(X1, X2)
plt.pcolormesh(x1, x2, F, norm=mpl.colors.LogNorm(), shading="auto")
plt.colorbar()
plt.xlabel("x1")
plt.ylabel("x2")
[1]:
Text(0, 0.5, 'x2')
The optimization goes faster if our model understands how the function changes as we change the inputs in different ways. The way it picks up on this is by starting from a general model that could describe a lot of functions, and making it specific to this one by choosing the right hyperparameters. Our Bayesian agent is very good at this, and only needs a few samples to figure out what the function looks like:
[2]:
def digestion(df):
for index, entry in df.iterrows():
df.loc[index, "booth"] = functions.booth(entry.x1, entry.x2)
return df
[3]:
from blop.utils import prepare_re_env
%run -i $prepare_re_env.__file__ --db-type=temp
from blop import DOF, Objective, Agent
dofs = [
DOF(name="x1", search_domain=(-6, 6)),
DOF(name="x2", search_domain=(-6, 6)),
]
objectives = [
Objective(name="booth", target="min"),
]
agent = Agent(
dofs=dofs,
objectives=objectives,
digestion=digestion,
db=db,
)
RE(agent.learn(acqf="qr", n=16))
agent.plot_objectives()
Transient Scan ID: 1 Time: 2024-09-26 23:32:44
Persistent Unique Scan ID: 'b66f95d7-2f35-4c6f-8cc7-a117956f2dcc'
New stream: 'primary'
+-----------+------------+------------+------------+
| seq_num | time | x1 | x2 |
+-----------+------------+------------+------------+
| 1 | 23:32:44.9 | 0.053 | 0.037 |
| 2 | 23:32:44.9 | 1.227 | -0.377 |
| 3 | 23:32:44.9 | -0.655 | -1.517 |
| 4 | 23:32:44.9 | -1.069 | 1.904 |
| 5 | 23:32:44.9 | -1.959 | 4.066 |
| 6 | 23:32:44.9 | -3.402 | 4.687 |
| 7 | 23:32:44.9 | -5.605 | 1.400 |
| 8 | 23:32:44.9 | -5.092 | -0.989 |
| 9 | 23:32:44.9 | -3.921 | -5.026 |
| 10 | 23:32:44.9 | -2.390 | -4.429 |
| 11 | 23:32:44.9 | 1.743 | -5.539 |
| 12 | 23:32:44.9 | 3.209 | -3.160 |
| 13 | 23:32:44.9 | 5.787 | -2.873 |
| 14 | 23:32:44.9 | 4.513 | 2.510 |
| 15 | 23:32:44.9 | 4.465 | 3.547 |
| 16 | 23:32:44.9 | 2.911 | 5.949 |
+-----------+------------+------------+------------+
generator list_scan ['b66f95d7'] (scan num: 1)
In addition to modeling the fitness of the task, the agent models the probability that an input will be feasible:
[4]:
agent.plot_acquisition(acqf="qei")
[5]:
RE(agent.learn("qei", n=4, iterations=4))
agent.plot_objectives()
Transient Scan ID: 2 Time: 2024-09-26 23:32:48
Persistent Unique Scan ID: '5d478a07-e84a-4805-86d5-72dd7b7bfe95'
New stream: 'primary'
+-----------+------------+------------+------------+
| seq_num | time | x1 | x2 |
+-----------+------------+------------+------------+
| 1 | 23:32:48.9 | -1.613 | 6.000 |
| 2 | 23:32:48.9 | 0.605 | 3.062 |
| 3 | 23:32:48.9 | 1.873 | 2.024 |
| 4 | 23:32:48.9 | 3.378 | 0.549 |
+-----------+------------+------------+------------+
generator list_scan ['5d478a07'] (scan num: 2)
Transient Scan ID: 3 Time: 2024-09-26 23:32:52
Persistent Unique Scan ID: 'ac5cb757-d5e4-432f-880b-e9543b7240fa'
New stream: 'primary'
+-----------+------------+------------+------------+
| seq_num | time | x1 | x2 |
+-----------+------------+------------+------------+
| 1 | 23:32:52.1 | 1.101 | 2.775 |
| 2 | 23:32:52.1 | 1.078 | 3.029 |
| 3 | 23:32:52.1 | 0.354 | 3.653 |
| 4 | 23:32:52.1 | 0.049 | 3.938 |
+-----------+------------+------------+------------+
generator list_scan ['ac5cb757'] (scan num: 3)
Transient Scan ID: 4 Time: 2024-09-26 23:32:53
Persistent Unique Scan ID: 'fb845a41-f488-497f-bcd5-56cd3c8c45e8'
New stream: 'primary'
+-----------+------------+------------+------------+
| seq_num | time | x1 | x2 |
+-----------+------------+------------+------------+
| 1 | 23:32:53.1 | 0.870 | 3.161 |
| 2 | 23:32:53.1 | 0.993 | 2.997 |
| 3 | 23:32:53.1 | 1.179 | 2.899 |
| 4 | 23:32:53.1 | 1.173 | 2.787 |
+-----------+------------+------------+------------+
generator list_scan ['fb845a41'] (scan num: 4)
/opt/hostedtoolcache/Python/3.10.15/x64/lib/python3.10/site-packages/botorch/optim/optimize.py:235: RuntimeWarning: Optimization failed in `gen_candidates_scipy` with the following warning(s):
[OptimizationWarning('Optimization failed within `scipy.optimize.minimize` with status 2 and message ABNORMAL_TERMINATION_IN_LNSRCH.')]
Trying again with a new set of initial conditions.
candidate, acq_value = _optimize_acqf_batch(new_inputs)
Transient Scan ID: 5 Time: 2024-09-26 23:32:54
Persistent Unique Scan ID: '34fc3323-8e52-4bb8-a2e7-ec55a0b6d831'
New stream: 'primary'
+-----------+------------+------------+------------+
| seq_num | time | x1 | x2 |
+-----------+------------+------------+------------+
| 1 | 23:32:54.1 | 1.106 | 2.841 |
| 2 | 23:32:54.1 | 0.975 | 3.010 |
| 3 | 23:32:54.1 | 0.923 | 2.984 |
| 4 | 23:32:54.1 | 0.893 | 3.142 |
+-----------+------------+------------+------------+
generator list_scan ['34fc3323'] (scan num: 5)
[6]:
agent.best
[6]:
x1 0.992979
x2 2.997489
booth 0.000419
time 2024-09-26 23:32:53.165735006
acqf monte_carlo_expected_improvement
Name: 25, dtype: object