16
16
17
17
from bayes_opt import acquisition
18
18
from bayes_opt .constraint import ConstraintModel
19
+ from bayes_opt .domain_reduction import DomainTransformer
19
20
from bayes_opt .event import DEFAULT_EVENTS , Events
20
21
from bayes_opt .logger import _get_default_logger
22
+ from bayes_opt .parameter import wrap_kernel
21
23
from bayes_opt .target_space import TargetSpace
22
24
from bayes_opt .util import ensure_rng
23
25
24
26
if TYPE_CHECKING :
25
- from collections .abc import Callable , Iterable , Mapping , Sequence
27
+ from collections .abc import Callable , Iterable , Mapping
26
28
27
29
from numpy .random import RandomState
28
30
from numpy .typing import NDArray
31
33
from bayes_opt .acquisition import AcquisitionFunction
32
34
from bayes_opt .constraint import ConstraintModel
33
35
from bayes_opt .domain_reduction import DomainTransformer
36
+ from bayes_opt .parameter import BoundsMapping , ParamsType
34
37
35
38
Float = np .floating [Any ]
36
39
@@ -114,7 +117,7 @@ def __init__(
114
117
):
115
118
self ._random_state = ensure_rng (random_state )
116
119
self ._allow_duplicate_points = allow_duplicate_points
117
- self ._queue : deque [Mapping [ str , float ] | Sequence [ float ] | NDArray [ Float ] ] = deque ()
120
+ self ._queue : deque [ParamsType ] = deque ()
118
121
119
122
if acquisition_function is None :
120
123
if constraint is None :
@@ -128,15 +131,6 @@ def __init__(
128
131
else :
129
132
self ._acquisition_function = acquisition_function
130
133
131
- # Internal GP regressor
132
- self ._gp = GaussianProcessRegressor (
133
- kernel = Matern (nu = 2.5 ),
134
- alpha = 1e-6 ,
135
- normalize_y = True ,
136
- n_restarts_optimizer = 5 ,
137
- random_state = self ._random_state ,
138
- )
139
-
140
134
if constraint is None :
141
135
# Data structure containing the function to be optimized, the
142
136
# bounds of its domain, and a record of the evaluations we have
@@ -158,14 +152,22 @@ def __init__(
158
152
)
159
153
self .is_constrained = True
160
154
155
+ # Internal GP regressor
156
+ self ._gp = GaussianProcessRegressor (
157
+ kernel = wrap_kernel (Matern (nu = 2.5 ), transform = self ._space .kernel_transform ),
158
+ alpha = 1e-6 ,
159
+ normalize_y = True ,
160
+ n_restarts_optimizer = 5 ,
161
+ random_state = self ._random_state ,
162
+ )
163
+
161
164
self ._verbose = verbose
162
165
self ._bounds_transformer = bounds_transformer
163
166
if self ._bounds_transformer :
164
- try :
165
- self ._bounds_transformer .initialize (self ._space )
166
- except (AttributeError , TypeError ) as exc :
167
- error_msg = "The transformer must be an instance of DomainTransformer"
168
- raise TypeError (error_msg ) from exc
167
+ if not isinstance (self ._bounds_transformer , DomainTransformer ):
168
+ msg = "The transformer must be an instance of DomainTransformer"
169
+ raise TypeError (msg )
170
+ self ._bounds_transformer .initialize (self ._space )
169
171
170
172
self ._sorting_warning_already_shown = False # TODO: remove in future version
171
173
super ().__init__ (events = DEFAULT_EVENTS )
@@ -204,10 +206,7 @@ def res(self) -> list[dict[str, Any]]:
204
206
return self ._space .res ()
205
207
206
208
def register (
207
- self ,
208
- params : Mapping [str , float ] | Sequence [float ] | NDArray [Float ],
209
- target : float ,
210
- constraint_value : float | NDArray [Float ] | None = None ,
209
+ self , params : ParamsType , target : float , constraint_value : float | NDArray [Float ] | None = None
211
210
) -> None :
212
211
"""Register an observation with known target.
213
212
@@ -225,20 +224,18 @@ def register(
225
224
# TODO: remove in future version
226
225
if isinstance (params , np .ndarray ) and not self ._sorting_warning_already_shown :
227
226
msg = (
228
- "You're attempting to register an np.ndarray. Currently , the optimizer internally sorts "
229
- " parameters by key and expects any registered array to respect this order. In future "
230
- " versions this behaviour will change and the order as given by the pbounds dictionary"
231
- " will be used. If you wish to retain sorted parameters, please manually sort your pbounds"
227
+ "You're attempting to register an np.ndarray. In previous versions , the optimizer internally"
228
+ " sorted parameters by key and expected any registered array to respect this order."
229
+ " In the current and any future version the order as given by the pbounds dictionary will be "
230
+ " used. If you wish to retain sorted parameters, please manually sort your pbounds"
232
231
" dictionary before constructing the optimizer."
233
232
)
234
233
warn (msg , stacklevel = 1 )
235
234
self ._sorting_warning_already_shown = True
236
235
self ._space .register (params , target , constraint_value )
237
236
self .dispatch (Events .OPTIMIZATION_STEP )
238
237
239
- def probe (
240
- self , params : Mapping [str , float ] | Sequence [float ] | NDArray [Float ], lazy : bool = True
241
- ) -> None :
238
+ def probe (self , params : ParamsType , lazy : bool = True ) -> None :
242
239
"""Evaluate the function at the given points.
243
240
244
241
Useful to guide the optimizer.
@@ -255,10 +252,10 @@ def probe(
255
252
# TODO: remove in future version
256
253
if isinstance (params , np .ndarray ) and not self ._sorting_warning_already_shown :
257
254
msg = (
258
- "You're attempting to register an np.ndarray. Currently , the optimizer internally sorts "
259
- " parameters by key and expects any registered array to respect this order. In future "
260
- " versions this behaviour will change and the order as given by the pbounds dictionary"
261
- " will be used. If you wish to retain sorted parameters, please manually sort your pbounds"
255
+ "You're attempting to register an np.ndarray. In previous versions , the optimizer internally"
256
+ " sorted parameters by key and expected any registered array to respect this order."
257
+ " In the current and any future version the order as given by the pbounds dictionary will be "
258
+ " used. If you wish to retain sorted parameters, please manually sort your pbounds"
262
259
" dictionary before constructing the optimizer."
263
260
)
264
261
warn (msg , stacklevel = 1 )
@@ -270,10 +267,10 @@ def probe(
270
267
self ._space .probe (params )
271
268
self .dispatch (Events .OPTIMIZATION_STEP )
272
269
273
- def suggest (self ) -> dict [str , float ]:
270
+ def suggest (self ) -> dict [str , float | NDArray [ Float ] ]:
274
271
"""Suggest a promising point to probe next."""
275
272
if len (self ._space ) == 0 :
276
- return self ._space .array_to_params (self ._space .random_sample ())
273
+ return self ._space .array_to_params (self ._space .random_sample (random_state = self . _random_state ))
277
274
278
275
# Finding argmax of the acquisition function.
279
276
suggestion = self ._acquisition_function .suggest (gp = self ._gp , target_space = self ._space , fit_gp = True )
@@ -292,7 +289,7 @@ def _prime_queue(self, init_points: int) -> None:
292
289
init_points = max (init_points , 1 )
293
290
294
291
for _ in range (init_points ):
295
- sample = self ._space .random_sample ()
292
+ sample = self ._space .random_sample (random_state = self . _random_state )
296
293
self ._queue .append (self ._space .array_to_params (sample ))
297
294
298
295
def _prime_subscriptions (self ) -> None :
@@ -344,7 +341,7 @@ def maximize(self, init_points: int = 5, n_iter: int = 25) -> None:
344
341
345
342
self .dispatch (Events .OPTIMIZATION_END )
346
343
347
- def set_bounds (self , new_bounds : Mapping [ str , NDArray [ Float ] | Sequence [ float ]] ) -> None :
344
+ def set_bounds (self , new_bounds : BoundsMapping ) -> None :
348
345
"""Modify the bounds of the search space.
349
346
350
347
Parameters
@@ -356,4 +353,6 @@ def set_bounds(self, new_bounds: Mapping[str, NDArray[Float] | Sequence[float]])
356
353
357
354
def set_gp_params (self , ** params : Any ) -> None :
358
355
"""Set parameters of the internal Gaussian Process Regressor."""
356
+ if "kernel" in params :
357
+ params ["kernel" ] = wrap_kernel (kernel = params ["kernel" ], transform = self ._space .kernel_transform )
359
358
self ._gp .set_params (** params )
0 commit comments