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 matplotlib as mpl
import numpy as np
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')
../_images/tutorials_hyperparameters_1_1.png

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  # noqa

%run -i $prepare_re_env.__file__ --db-type=temp

from blop import DOF, Agent, Objective

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()
2025-06-19 02:05:42.823 INFO: Executing plan <generator object Agent.learn at 0x7f0a002a6e30>
2025-06-19 02:05:42.825 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f0a00349bd0> from 'idle' -> 'running'


Transient Scan ID: 1     Time: 2025-06-19 02:05:42
Persistent Unique Scan ID: '90361ad3-3ae4-4b41-af59-cf5c7f46073c'
New stream: 'primary'
+-----------+------------+------------+------------+
|   seq_num |       time |         x1 |         x2 |
+-----------+------------+------------+------------+
|         1 | 02:05:42.9 |      0.410 |     -0.554 |
|         2 | 02:05:42.9 |      1.083 |      1.443 |
|         3 | 02:05:42.9 |      3.417 |      2.617 |
|         4 | 02:05:42.9 |      5.589 |      5.563 |
|         5 | 02:05:42.9 |      1.911 |      4.486 |
|         6 | 02:05:42.9 |     -0.172 |      5.148 |
|         7 | 02:05:42.9 |     -2.833 |      2.094 |
|         8 | 02:05:42.9 |     -4.328 |      3.225 |
|         9 | 02:05:42.9 |     -4.667 |      0.268 |
|        10 | 02:05:42.9 |     -5.821 |     -0.782 |
|        11 | 02:05:43.0 |     -3.185 |     -3.835 |
|        12 | 02:05:43.0 |     -1.680 |     -2.705 |
|        13 | 02:05:43.0 |     -1.315 |     -5.662 |
|        14 | 02:05:43.0 |      2.597 |     -3.501 |
|        15 | 02:05:43.0 |      4.903 |     -4.673 |
|        16 | 02:05:43.0 |      4.090 |     -1.631 |
+-----------+------------+------------+------------+
generator list_scan ['90361ad3'] (scan num: 1)



2025-06-19 02:05:43.818 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f0a00349bd0> from 'running' -> 'idle'
2025-06-19 02:05:43.820 INFO: Cleaned up from plan <generator object Agent.learn at 0x7f0a002a6e30>
../_images/tutorials_hyperparameters_4_3.png

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")
../_images/tutorials_hyperparameters_6_0.png
[5]:
RE(agent.learn("qei", n=4, iterations=4))
agent.plot_objectives()
2025-06-19 02:05:45.600 INFO: Executing plan <generator object Agent.learn at 0x7f09ebb6fe60>
2025-06-19 02:05:45.602 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f0a00349bd0> from 'idle' -> 'running'


Transient Scan ID: 2     Time: 2025-06-19 02:05:47
Persistent Unique Scan ID: '6d744d37-c0d6-49da-b3d6-700fd1291acf'
New stream: 'primary'
+-----------+------------+------------+------------+
|   seq_num |       time |         x1 |         x2 |
+-----------+------------+------------+------------+
|         1 | 02:05:47.3 |      2.256 |      1.722 |
|         2 | 02:05:47.3 |      1.197 |      2.876 |
|         3 | 02:05:47.3 |      0.471 |      3.478 |
|         4 | 02:05:47.3 |     -2.308 |      6.000 |
+-----------+------------+------------+------------+
generator list_scan ['6d744d37'] (scan num: 2)



/opt/hostedtoolcache/Python/3.10.17/x64/lib/python3.10/site-packages/botorch/fit.py:215: OptimizationWarning: `scipy_minimize` terminated with status 3, displaying original message from `scipy.optimize.minimize`: ABNORMAL:
  result = optimizer(mll, closure=closure, **optimizer_kwargs)


Transient Scan ID: 3     Time: 2025-06-19 02:05:51
Persistent Unique Scan ID: '07319534-3a9d-4426-b036-afd6bffcbac1'
New stream: 'primary'
+-----------+------------+------------+------------+
|   seq_num |       time |         x1 |         x2 |
+-----------+------------+------------+------------+
|         1 | 02:05:52.0 |     -0.296 |      4.064 |
|         2 | 02:05:52.0 |      0.943 |      3.055 |
|         3 | 02:05:52.0 |      0.940 |      2.901 |
|         4 | 02:05:52.0 |      1.399 |      2.642 |
+-----------+------------+------------+------------+
generator list_scan ['07319534'] (scan num: 3)





Transient Scan ID: 4     Time: 2025-06-19 02:05:55
Persistent Unique Scan ID: '9b756e55-7a97-493e-80ab-9a37b967469d'
New stream: 'primary'
+-----------+------------+------------+------------+
|   seq_num |       time |         x1 |         x2 |
+-----------+------------+------------+------------+
|         1 | 02:05:55.6 |      1.030 |      2.904 |
|         2 | 02:05:55.6 |      0.986 |      3.051 |
|         3 | 02:05:55.6 |      0.941 |      3.180 |
|         4 | 02:05:55.6 |      6.000 |     -0.550 |
+-----------+------------+------------+------------+
generator list_scan ['9b756e55'] (scan num: 4)





Transient Scan ID: 5     Time: 2025-06-19 02:05:57
Persistent Unique Scan ID: '33a00f2d-268f-404b-8a0e-00a7543383df'
New stream: 'primary'
+-----------+------------+------------+------------+
|   seq_num |       time |         x1 |         x2 |
+-----------+------------+------------+------------+
|         1 | 02:05:57.2 |      1.127 |      2.876 |
|         2 | 02:05:57.2 |      0.999 |      3.012 |
|         3 | 02:05:57.2 |      0.963 |      3.123 |
|         4 | 02:05:57.2 |      0.868 |      3.078 |
+-----------+------------+------------+------------+
generator list_scan ['33a00f2d'] (scan num: 5)



2025-06-19 02:05:57.580 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f0a00349bd0> from 'running' -> 'idle'
2025-06-19 02:05:57.582 INFO: Cleaned up from plan <generator object Agent.learn at 0x7f09ebb6fe60>
../_images/tutorials_hyperparameters_7_5.png
[6]:
agent.best
[6]:
x1                                0.99921
x2                               3.011767
booth                            0.000621
time        2025-06-19 02:05:57.227891684
acqf     monte_carlo_expected_improvement
Name: 29, dtype: object