Skip to content

Commit 0f14490

Browse files
committed
deploy: 626aafe
1 parent 99f4954 commit 0f14490

15 files changed

+1429
-501
lines changed

master/_sources/acquisition_functions.ipynb.txt

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,25 @@
5454
" 'Gaussian Process and Utility Function After {} Steps'.format(steps),\n",
5555
" fontsize=30\n",
5656
" )\n",
57-
" \n",
58-
" gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1]) \n",
57+
"\n",
58+
" gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1])\n",
5959
" axis = plt.subplot(gs[0])\n",
6060
" acq = plt.subplot(gs[1])\n",
61-
" \n",
61+
"\n",
6262
" x_obs = np.array([[res[\"params\"][\"x\"]] for res in optimizer.res])\n",
6363
" y_obs = np.array([res[\"target\"] for res in optimizer.res])\n",
64-
" \n",
64+
"\n",
6565
" acquisition_function_._fit_gp(optimizer._gp, optimizer._space)\n",
6666
" mu, sigma = posterior(optimizer, x)\n",
6767
"\n",
6868
" axis.plot(x, y, linewidth=3, label='Target')\n",
6969
" axis.plot(x_obs.flatten(), y_obs, 'D', markersize=8, label=u'Observations', color='r')\n",
7070
" axis.plot(x, mu, '--', color='k', label='Prediction')\n",
7171
"\n",
72-
" axis.fill(np.concatenate([x, x[::-1]]), \n",
72+
" axis.fill(np.concatenate([x, x[::-1]]),\n",
7373
" np.concatenate([mu - 1.9600 * sigma, (mu + 1.9600 * sigma)[::-1]]),\n",
7474
" alpha=.6, fc='c', ec='None', label='95% confidence interval')\n",
75-
" \n",
75+
"\n",
7676
" axis.set_xlim((-2, 10))\n",
7777
" axis.set_ylim((None, None))\n",
7878
" axis.set_ylabel('f(x)', fontdict={'size':20})\n",
@@ -82,13 +82,13 @@
8282
" x = x.flatten()\n",
8383
"\n",
8484
" acq.plot(x, utility, label='Utility Function', color='purple')\n",
85-
" acq.plot(x[np.argmax(utility)], np.max(utility), '*', markersize=15, \n",
85+
" acq.plot(x[np.argmax(utility)], np.max(utility), '*', markersize=15,\n",
8686
" label=u'Next Best Guess', markerfacecolor='gold', markeredgecolor='k', markeredgewidth=1)\n",
8787
" acq.set_xlim((-2, 10))\n",
8888
" #acq.set_ylim((0, np.max(utility) + 0.5))\n",
8989
" acq.set_ylabel('Utility', fontdict={'size':20})\n",
9090
" acq.set_xlabel('x', fontdict={'size':20})\n",
91-
" \n",
91+
"\n",
9292
" axis.legend(loc=2, bbox_to_anchor=(1.01, 1), borderaxespad=0.)\n",
9393
" acq.legend(loc=2, bbox_to_anchor=(1.01, 1), borderaxespad=0.)\n",
9494
" return fig, fig.axes"
@@ -110,7 +110,7 @@
110110
"class GreedyAcquisition(acquisition.AcquisitionFunction):\n",
111111
" def __init__(self, random_state=None):\n",
112112
" super().__init__(random_state)\n",
113-
" \n",
113+
"\n",
114114
" def base_acq(self, mean, std):\n",
115115
" return mean # disregard std"
116116
]
@@ -357,11 +357,17 @@
357357
]
358358
},
359359
{
360-
"cell_type": "code",
361-
"execution_count": null,
360+
"cell_type": "markdown",
362361
"metadata": {},
363-
"outputs": [],
364-
"source": []
362+
"source": [
363+
"### Saving and loading with custom acquisition functions\n",
364+
"\n",
365+
"If saving and loading is desired functionality, the acquisition function needs to have a `get_acquisition_params` and `set_acquisition_params` method.\n",
366+
"\n",
367+
"Default acquisition functions have a `get_acquisition_params` and `set_acquisition_params` method that is used to save and load the acquisition function state when the optimizer is being saved and loaded. When writing and using a custom acquisition function, those methods need to also be defined. In order to have perfect replicability, all parameters that the acquisition function depends on need to be saved and loaded. The get_acquisition_params method should return a dictionary containing all acquisition function parameters. The set_acquisition_params method should take that same dictionary containing the acquisition function parameters and update the respective parameters.\n",
368+
"\n",
369+
"_serialize_random_state and _deserialize_random_state are provided as part of the base class and should be included in the dictionary returned by `get_acquisition_params`. See any of the default acquisition functions for reference."
370+
]
365371
},
366372
{
367373
"cell_type": "code",

master/_sources/basic-tour.ipynb.txt

Lines changed: 48 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@
106106
"text": [
107107
"| iter | target | x | y |\n",
108108
"-------------------------------------------------\n",
109-
"| \u001b[0m1 \u001b[0m | \u001b[0m-7.135 \u001b[0m | \u001b[0m2.834 \u001b[0m | \u001b[0m1.322 \u001b[0m |\n",
110-
"| \u001b[0m2 \u001b[0m | \u001b[0m-7.78 \u001b[0m | \u001b[0m2.0 \u001b[0m | \u001b[0m-1.186 \u001b[0m |\n",
111-
"| \u001b[95m3 \u001b[0m | \u001b[95m-6.967 \u001b[0m | \u001b[95m2.582 \u001b[0m | \u001b[95m-0.1396 \u001b[0m |\n",
112-
"| \u001b[0m4 \u001b[0m | \u001b[0m-12.24 \u001b[0m | \u001b[0m2.015 \u001b[0m | \u001b[0m-2.029 \u001b[0m |\n",
113-
"| \u001b[0m5 \u001b[0m | \u001b[0m-18.0 \u001b[0m | \u001b[0m3.302 \u001b[0m | \u001b[0m-1.846 \u001b[0m |\n",
109+
"| \u001b[39m1 \u001b[39m | \u001b[39m-7.135 \u001b[39m | \u001b[39m2.8340440\u001b[39m | \u001b[39m1.3219469\u001b[39m |\n",
110+
"| \u001b[39m2 \u001b[39m | \u001b[39m-7.78 \u001b[39m | \u001b[39m2.0002287\u001b[39m | \u001b[39m-1.186004\u001b[39m |\n",
111+
"| \u001b[39m3 \u001b[39m | \u001b[39m-7.157 \u001b[39m | \u001b[39m2.8375977\u001b[39m | \u001b[39m1.3238498\u001b[39m |\n",
112+
"| \u001b[35m4 \u001b[39m | \u001b[35m-6.633 \u001b[39m | \u001b[35m2.7487090\u001b[39m | \u001b[35m1.2790562\u001b[39m |\n",
113+
"| \u001b[35m5 \u001b[39m | \u001b[35m-5.751 \u001b[39m | \u001b[35m2.5885326\u001b[39m | \u001b[35m1.2246876\u001b[39m |\n",
114114
"=================================================\n"
115115
]
116116
}
@@ -138,7 +138,7 @@
138138
"name": "stdout",
139139
"output_type": "stream",
140140
"text": [
141-
"{'target': -6.966506881014352, 'params': {'x': 2.5822074982517598, 'y': -0.13961016009280103}}\n"
141+
"{'target': np.float64(-5.750985875689304), 'params': {'x': np.float64(2.5885326650623566), 'y': np.float64(1.2246876000015976)}}\n"
142142
]
143143
}
144144
],
@@ -163,15 +163,15 @@
163163
"output_type": "stream",
164164
"text": [
165165
"Iteration 0: \n",
166-
"\t{'target': -7.135455292718879, 'params': {'x': 2.8340440094051482, 'y': 1.3219469606529486}}\n",
166+
"\t{'target': np.float64(-7.135455292718879), 'params': {'x': np.float64(2.8340440094051482), 'y': np.float64(1.3219469606529486)}}\n",
167167
"Iteration 1: \n",
168-
"\t{'target': -7.779531005607566, 'params': {'x': 2.0002287496346898, 'y': -1.1860045642089614}}\n",
168+
"\t{'target': np.float64(-7.779531005607566), 'params': {'x': np.float64(2.0002287496346898), 'y': np.float64(-1.1860045642089614)}}\n",
169169
"Iteration 2: \n",
170-
"\t{'target': -6.966506881014352, 'params': {'x': 2.5822074982517598, 'y': -0.13961016009280103}}\n",
170+
"\t{'target': np.float64(-7.156839989425082), 'params': {'x': np.float64(2.8375977943744273), 'y': np.float64(1.3238498831039895)}}\n",
171171
"Iteration 3: \n",
172-
"\t{'target': -12.235835023240657, 'params': {'x': 2.0154397119682423, 'y': -2.0288343947238228}}\n",
172+
"\t{'target': np.float64(-6.633273772355583), 'params': {'x': np.float64(2.7487090390562576), 'y': np.float64(1.2790562505410115)}}\n",
173173
"Iteration 4: \n",
174-
"\t{'target': -17.99963711795217, 'params': {'x': 3.301617813728339, 'y': -1.8458666395359906}}\n"
174+
"\t{'target': np.float64(-5.750985875689304), 'params': {'x': np.float64(2.5885326650623566), 'y': np.float64(1.2246876000015976)}}\n"
175175
]
176176
}
177177
],
@@ -209,11 +209,11 @@
209209
"text": [
210210
"| iter | target | x | y |\n",
211211
"-------------------------------------------------\n",
212-
"| \u001b[95m6 \u001b[0m | \u001b[95m-1.378 \u001b[0m | \u001b[95m1.229 \u001b[0m | \u001b[95m0.06916 \u001b[0m |\n",
213-
"| \u001b[95m7 \u001b[0m | \u001b[95m-0.9471 \u001b[0m | \u001b[95m-0.9434 \u001b[0m | \u001b[95m-0.02816 \u001b[0m |\n",
214-
"| \u001b[0m8 \u001b[0m | \u001b[0m-3.651 \u001b[0m | \u001b[0m-1.168 \u001b[0m | \u001b[0m2.813 \u001b[0m |\n",
215-
"| \u001b[0m9 \u001b[0m | \u001b[0m-17.13 \u001b[0m | \u001b[0m-2.0 \u001b[0m | \u001b[0m-2.758 \u001b[0m |\n",
216-
"| \u001b[95m10 \u001b[0m | \u001b[95m0.8427 \u001b[0m | \u001b[95m-0.193 \u001b[0m | \u001b[95m0.6535 \u001b[0m |\n",
212+
"| \u001b[35m6 \u001b[39m | \u001b[35m-4.438 \u001b[39m | \u001b[35m2.3269441\u001b[39m | \u001b[35m1.1533794\u001b[39m |\n",
213+
"| \u001b[35m7 \u001b[39m | \u001b[35m-2.42 \u001b[39m | \u001b[35m1.8477442\u001b[39m | \u001b[35m0.9230233\u001b[39m |\n",
214+
"| \u001b[35m8 \u001b[39m | \u001b[35m-0.2088 \u001b[39m | \u001b[35m1.0781674\u001b[39m | \u001b[35m1.2152869\u001b[39m |\n",
215+
"| \u001b[35m9 \u001b[39m | \u001b[35m0.7797 \u001b[39m | \u001b[35m-0.298812\u001b[39m | \u001b[35m1.3619705\u001b[39m |\n",
216+
"| \u001b[39m10 \u001b[39m | \u001b[39m-3.391 \u001b[39m | \u001b[39m-0.655060\u001b[39m | \u001b[39m2.9904883\u001b[39m |\n",
217217
"=================================================\n"
218218
]
219219
}
@@ -295,8 +295,8 @@
295295
"text": [
296296
"| iter | target | x | y |\n",
297297
"-------------------------------------------------\n",
298-
"| \u001b[0m11 \u001b[0m | \u001b[0m0.66 \u001b[0m | \u001b[0m0.5 \u001b[0m | \u001b[0m0.7 \u001b[0m |\n",
299-
"| \u001b[0m12 \u001b[0m | \u001b[0m0.1 \u001b[0m | \u001b[0m-0.3 \u001b[0m | \u001b[0m0.1 \u001b[0m |\n",
298+
"| \u001b[39m11 \u001b[39m | \u001b[39m0.66 \u001b[39m | \u001b[39m0.5 \u001b[39m | \u001b[39m0.7 \u001b[39m |\n",
299+
"| \u001b[39m12 \u001b[39m | \u001b[39m0.1 \u001b[39m | \u001b[39m-0.3 \u001b[39m | \u001b[39m0.1 \u001b[39m |\n",
300300
"=================================================\n"
301301
]
302302
}
@@ -309,176 +309,68 @@
309309
"cell_type": "markdown",
310310
"metadata": {},
311311
"source": [
312-
"## 4. Saving, loading and restarting\n",
312+
"## 4. Saving and loading the optimizer\n",
313313
"\n",
314-
"By default you can follow the progress of your optimization by setting `verbose>0` when instantiating the `BayesianOptimization` object. If you need more control over logging/alerting you will need to use an observer. For more information about observers checkout the advanced tour notebook. Here we will only see how to use the native `JSONLogger` object to save to and load progress from files.\n",
314+
"The optimizer state can be saved to a file and loaded from a file. This is useful for continuing an optimization from a previous state, or for analyzing the optimization history without running the optimizer again.\n",
315315
"\n",
316-
"### 4.1 Saving progress"
317-
]
318-
},
319-
{
320-
"cell_type": "code",
321-
"execution_count": 14,
322-
"metadata": {},
323-
"outputs": [],
324-
"source": [
325-
"from bayes_opt.logger import JSONLogger\n",
326-
"from bayes_opt.event import Events"
316+
"Note: if you are using your own custom acquisition function, you will need to save and load the acquisition function state as well. This is done by calling the `get_acquisition_params` and `set_acquisition_params` methods of the acquisition function. See the acquisition function documentation for more information."
327317
]
328318
},
329319
{
330320
"cell_type": "markdown",
331321
"metadata": {},
332322
"source": [
333-
"The observer paradigm works by:\n",
334-
"1. Instantiating an observer object.\n",
335-
"2. Tying the observer object to a particular event fired by an optimizer.\n",
336-
"\n",
337-
"The `BayesianOptimization` object fires a number of internal events during optimization, in particular, every time it probes the function and obtains a new parameter-target combination it will fire an `Events.OPTIMIZATION_STEP` event, which our logger will listen to.\n",
323+
"### 4.1 Saving the optimizer state\n",
338324
"\n",
339-
"**Caveat:** The logger will not look back at previously probed points."
325+
"The optimizer state can be saved to a file using the `save_state` method.\n",
326+
"optimizer.save_state(\"./optimizer_state.json\")"
340327
]
341328
},
342329
{
343330
"cell_type": "code",
344-
"execution_count": 15,
331+
"execution_count": 22,
345332
"metadata": {},
346333
"outputs": [],
347334
"source": [
348-
"logger = JSONLogger(path=\"./logs.log\")\n",
349-
"optimizer.subscribe(Events.OPTIMIZATION_STEP, logger)"
350-
]
351-
},
352-
{
353-
"cell_type": "code",
354-
"execution_count": 16,
355-
"metadata": {},
356-
"outputs": [
357-
{
358-
"name": "stdout",
359-
"output_type": "stream",
360-
"text": [
361-
"| iter | target | x | y |\n",
362-
"-------------------------------------------------\n",
363-
"| \u001b[0m13 \u001b[0m | \u001b[0m-12.48 \u001b[0m | \u001b[0m-1.266 \u001b[0m | \u001b[0m-2.446 \u001b[0m |\n",
364-
"| \u001b[0m14 \u001b[0m | \u001b[0m-3.854 \u001b[0m | \u001b[0m-1.069 \u001b[0m | \u001b[0m-0.9266 \u001b[0m |\n",
365-
"| \u001b[95m15 \u001b[0m | \u001b[95m0.967 \u001b[0m | \u001b[95m0.04749 \u001b[0m | \u001b[95m1.175 \u001b[0m |\n",
366-
"| \u001b[95m16 \u001b[0m | \u001b[95m0.9912 \u001b[0m | \u001b[95m0.07374 \u001b[0m | \u001b[95m0.9421 \u001b[0m |\n",
367-
"| \u001b[0m17 \u001b[0m | \u001b[0m-3.565 \u001b[0m | \u001b[0m0.7821 \u001b[0m | \u001b[0m2.988 \u001b[0m |\n",
368-
"=================================================\n"
369-
]
370-
}
371-
],
372-
"source": [
373-
"optimizer.maximize(\n",
374-
" init_points=2,\n",
375-
" n_iter=3,\n",
376-
")"
335+
"optimizer.save_state(\"optimizer_state.json\")"
377336
]
378337
},
379338
{
380339
"cell_type": "markdown",
381340
"metadata": {},
382341
"source": [
383-
"### 4.2 Loading progress\n",
342+
"## 4.2 Loading the optimizer state\n",
384343
"\n",
385-
"Naturally, if you stored progress you will be able to load that onto a new instance of `BayesianOptimization`. The easiest way to do it is by invoking the `load_logs` function, from the `util` submodule."
344+
"To load with a previously saved state, pass the path of your saved state file to the `load_state_path` parameter. Note that if you've changed the bounds of your parameters, you'll need to pass the updated bounds to the new optimizer.\n"
386345
]
387346
},
388347
{
389348
"cell_type": "code",
390-
"execution_count": 17,
349+
"execution_count": 23,
391350
"metadata": {},
392351
"outputs": [],
393-
"source": [
394-
"from bayes_opt.util import load_logs"
395-
]
396-
},
397-
{
398-
"cell_type": "code",
399-
"execution_count": 18,
400-
"metadata": {},
401-
"outputs": [
402-
{
403-
"name": "stdout",
404-
"output_type": "stream",
405-
"text": [
406-
"0\n"
407-
]
408-
}
409-
],
410352
"source": [
411353
"new_optimizer = BayesianOptimization(\n",
412354
" f=black_box_function,\n",
413-
" pbounds={\"x\": (-2, 2), \"y\": (-2, 2)},\n",
414-
" verbose=2,\n",
415-
" random_state=7,\n",
355+
" pbounds={\"x\": (-2, 3), \"y\": (-3, 3)},\n",
356+
" random_state=1,\n",
357+
" verbose=0\n",
416358
")\n",
417-
"print(len(new_optimizer.space))"
418-
]
419-
},
420-
{
421-
"cell_type": "code",
422-
"execution_count": 19,
423-
"metadata": {},
424-
"outputs": [],
425-
"source": [
426-
"load_logs(new_optimizer, logs=[\"./logs.log\"]);"
359+
"\n",
360+
"new_optimizer.load_state(\"./optimizer_state.json\")\n",
361+
"\n",
362+
"# Continue optimization\n",
363+
"new_optimizer.maximize(\n",
364+
" init_points=0,\n",
365+
" n_iter=5\n",
366+
")"
427367
]
428368
},
429369
{
430-
"cell_type": "code",
431-
"execution_count": 20,
370+
"cell_type": "markdown",
432371
"metadata": {},
433-
"outputs": [
434-
{
435-
"name": "stdout",
436-
"output_type": "stream",
437-
"text": [
438-
"New optimizer is now aware of 5 points.\n"
439-
]
440-
}
441-
],
442372
"source": [
443-
"print(\"New optimizer is now aware of {} points.\".format(len(new_optimizer.space)))"
444-
]
445-
},
446-
{
447-
"cell_type": "code",
448-
"execution_count": 21,
449-
"metadata": {},
450-
"outputs": [
451-
{
452-
"name": "stdout",
453-
"output_type": "stream",
454-
"text": [
455-
"| iter | target | x | y |\n",
456-
"-------------------------------------------------\n",
457-
"| \u001b[0m1 \u001b[0m | \u001b[0m-0.6164 \u001b[0m | \u001b[0m-1.271 \u001b[0m | \u001b[0m1.045 \u001b[0m |\n"
458-
]
459-
},
460-
{
461-
"name": "stdout",
462-
"output_type": "stream",
463-
"text": [
464-
"| \u001b[95m2 \u001b[0m | \u001b[95m0.9988 \u001b[0m | \u001b[95m0.005532 \u001b[0m | \u001b[95m1.034 \u001b[0m |\n",
465-
"| \u001b[0m3 \u001b[0m | \u001b[0m0.9757 \u001b[0m | \u001b[0m0.1501 \u001b[0m | \u001b[0m1.043 \u001b[0m |\n",
466-
"| \u001b[0m4 \u001b[0m | \u001b[0m0.9819 \u001b[0m | \u001b[0m-0.07993 \u001b[0m | \u001b[0m0.8917 \u001b[0m |\n",
467-
"| \u001b[0m5 \u001b[0m | \u001b[0m-3.35 \u001b[0m | \u001b[0m1.976 \u001b[0m | \u001b[0m0.3338 \u001b[0m |\n",
468-
"| \u001b[0m6 \u001b[0m | \u001b[0m0.9778 \u001b[0m | \u001b[0m-0.1166 \u001b[0m | \u001b[0m1.093 \u001b[0m |\n",
469-
"| \u001b[0m7 \u001b[0m | \u001b[0m0.6605 \u001b[0m | \u001b[0m-0.02272 \u001b[0m | \u001b[0m0.4178 \u001b[0m |\n",
470-
"| \u001b[0m8 \u001b[0m | \u001b[0m-0.5044 \u001b[0m | \u001b[0m-0.7146 \u001b[0m | \u001b[0m1.997 \u001b[0m |\n",
471-
"| \u001b[95m9 \u001b[0m | \u001b[95m0.9997 \u001b[0m | \u001b[95m0.0084 \u001b[0m | \u001b[95m1.016 \u001b[0m |\n",
472-
"| \u001b[0m10 \u001b[0m | \u001b[0m-11.83 \u001b[0m | \u001b[0m1.995 \u001b[0m | \u001b[0m-1.974 \u001b[0m |\n",
473-
"=================================================\n"
474-
]
475-
}
476-
],
477-
"source": [
478-
"new_optimizer.maximize(\n",
479-
" init_points=0,\n",
480-
" n_iter=10,\n",
481-
")"
373+
"This provides a simpler alternative to the logging system shown in section 4, especially when you want to continue optimization from a previous state."
482374
]
483375
},
484376
{
@@ -489,6 +381,11 @@
489381
"\n",
490382
"This tour should be enough to cover most usage scenarios of this package. If, however, you feel like you need to know more, please checkout the `advanced-tour` notebook. There you will be able to find other, more advanced features of this package that could be what you're looking for. Also, browse the examples folder for implementation tips and ideas."
491383
]
384+
},
385+
{
386+
"cell_type": "markdown",
387+
"metadata": {},
388+
"source": []
492389
}
493390
],
494391
"metadata": {
@@ -507,7 +404,7 @@
507404
"name": "python",
508405
"nbconvert_exporter": "python",
509406
"pygments_lexer": "ipython3",
510-
"version": "3.10.0"
407+
"version": "3.13.1"
511408
}
512409
},
513410
"nbformat": 4,

0 commit comments

Comments
 (0)