Skip to content

Commit 8e19dc8

Browse files
authored
Replace event based logging (#557)
* remove observable pattern, jsonlogger, and any use of events * update notebooks to new logging system * update tests for new logging system * make ruff formatting tests pass * add tests for the screen logger class * pass in logger function arguments seperately * add tests to check params_config implementation * remove unnecessary attribute descriptions, move params_config to function argument * make verbosity level check explicit * format negative scientific notation correctly * use ternary operator to make computer happy * format parameter values correctly
1 parent 626aafe commit 8e19dc8

20 files changed

+690
-922
lines changed

bayes_opt/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
import importlib.metadata
66

77
from bayes_opt import acquisition
8-
from bayes_opt.bayesian_optimization import BayesianOptimization, Events
8+
from bayes_opt.bayesian_optimization import BayesianOptimization
99
from bayes_opt.constraint import ConstraintModel
1010
from bayes_opt.domain_reduction import SequentialDomainReductionTransformer
11-
from bayes_opt.logger import JSONLogger, ScreenLogger
11+
from bayes_opt.logger import ScreenLogger
1212
from bayes_opt.target_space import TargetSpace
1313

1414
__version__ = importlib.metadata.version("bayesian-optimization")
@@ -19,8 +19,6 @@
1919
"BayesianOptimization",
2020
"TargetSpace",
2121
"ConstraintModel",
22-
"Events",
2322
"ScreenLogger",
24-
"JSONLogger",
2523
"SequentialDomainReductionTransformer",
2624
]

bayes_opt/bayesian_optimization.py

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@
2121
from bayes_opt import acquisition
2222
from bayes_opt.constraint import ConstraintModel
2323
from bayes_opt.domain_reduction import DomainTransformer
24-
from bayes_opt.event import DEFAULT_EVENTS, Events
25-
from bayes_opt.logger import _get_default_logger
24+
from bayes_opt.logger import ScreenLogger
2625
from bayes_opt.parameter import wrap_kernel
2726
from bayes_opt.target_space import TargetSpace
2827
from bayes_opt.util import ensure_rng
2928

3029
if TYPE_CHECKING:
31-
from collections.abc import Callable, Iterable, Mapping
30+
from collections.abc import Callable, Mapping
3231

3332
from numpy.random import RandomState
3433
from numpy.typing import NDArray
@@ -41,35 +40,7 @@
4140
Float = np.floating[Any]
4241

4342

44-
class Observable:
45-
"""Inspired by https://www.protechtraining.com/blog/post/879#simple-observer."""
46-
47-
def __init__(self, events: Iterable[Any]) -> None:
48-
# maps event names to subscribers
49-
# str -> dict
50-
self._events = {event: dict() for event in events}
51-
52-
def get_subscribers(self, event: Any) -> Any:
53-
"""Return the subscribers of an event."""
54-
return self._events[event]
55-
56-
def subscribe(self, event: Any, subscriber: Any, callback: Callable[..., Any] | None = None) -> None:
57-
"""Add subscriber to an event."""
58-
if callback is None:
59-
callback = subscriber.update
60-
self.get_subscribers(event)[subscriber] = callback
61-
62-
def unsubscribe(self, event: Any, subscriber: Any) -> None:
63-
"""Remove a subscriber for a particular event."""
64-
del self.get_subscribers(event)[subscriber]
65-
66-
def dispatch(self, event: Any) -> None:
67-
"""Trigger callbacks for subscribers of an event."""
68-
for callback in self.get_subscribers(event).values():
69-
callback(event, self)
70-
71-
72-
class BayesianOptimization(Observable):
43+
class BayesianOptimization:
7344
"""Handle optimization of a target function over a specific target space.
7445
7546
This class takes the function to optimize as well as the parameters bounds
@@ -173,7 +144,9 @@ def __init__(
173144
self._bounds_transformer.initialize(self._space)
174145

175146
self._sorting_warning_already_shown = False # TODO: remove in future version
176-
super().__init__(events=DEFAULT_EVENTS)
147+
148+
# Initialize logger
149+
self.logger = ScreenLogger(verbose=self._verbose, is_constrained=self.is_constrained)
177150

178151
@property
179152
def space(self) -> TargetSpace:
@@ -236,7 +209,9 @@ def register(
236209
warn(msg, stacklevel=1)
237210
self._sorting_warning_already_shown = True
238211
self._space.register(params, target, constraint_value)
239-
self.dispatch(Events.OPTIMIZATION_STEP)
212+
self.logger.log_optimization_step(
213+
self._space.keys, self._space.res()[-1], self._space.params_config, self.max
214+
)
240215

241216
def probe(self, params: ParamsType, lazy: bool = True) -> None:
242217
"""Evaluate the function at the given points.
@@ -268,7 +243,9 @@ def probe(self, params: ParamsType, lazy: bool = True) -> None:
268243
self._queue.append(params)
269244
else:
270245
self._space.probe(params)
271-
self.dispatch(Events.OPTIMIZATION_STEP)
246+
self.logger.log_optimization_step(
247+
self._space.keys, self._space.res()[-1], self._space.params_config, self.max
248+
)
272249

273250
def suggest(self) -> dict[str, float | NDArray[Float]]:
274251
"""Suggest a promising point to probe next."""
@@ -295,13 +272,6 @@ def _prime_queue(self, init_points: int) -> None:
295272
sample = self._space.random_sample(random_state=self._random_state)
296273
self._queue.append(self._space.array_to_params(sample))
297274

298-
def _prime_subscriptions(self) -> None:
299-
if not any([len(subs) for subs in self._events.values()]):
300-
_logger = _get_default_logger(self._verbose, self.is_constrained)
301-
self.subscribe(Events.OPTIMIZATION_START, _logger)
302-
self.subscribe(Events.OPTIMIZATION_STEP, _logger)
303-
self.subscribe(Events.OPTIMIZATION_END, _logger)
304-
305275
def maximize(self, init_points: int = 5, n_iter: int = 25) -> None:
306276
r"""
307277
Maximize the given function over the target space.
@@ -324,8 +294,10 @@ def maximize(self, init_points: int = 5, n_iter: int = 25) -> None:
324294
optimization routine, make sure to fit it manually, e.g. by calling
325295
``optimizer._gp.fit(optimizer.space.params, optimizer.space.target)``.
326296
"""
327-
self._prime_subscriptions()
328-
self.dispatch(Events.OPTIMIZATION_START)
297+
# Log optimization start
298+
self.logger.log_optimization_start(self._space.keys)
299+
300+
# Prime the queue with random points
329301
self._prime_queue(init_points)
330302

331303
iteration = 0
@@ -342,7 +314,8 @@ def maximize(self, init_points: int = 5, n_iter: int = 25) -> None:
342314
# the init_points points (only for the true iterations)
343315
self.set_bounds(self._bounds_transformer.transform(self._space))
344316

345-
self.dispatch(Events.OPTIMIZATION_END)
317+
# Log optimization end
318+
self.logger.log_optimization_end()
346319

347320
def set_bounds(self, new_bounds: BoundsMapping) -> None:
348321
"""Modify the bounds of the search space.

bayes_opt/event.py

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)