pyuncertainnumber.opt.bo¶
Classes¶
Bayesian Optimisation class with original function signature (arguments signature). |
|
Bayesian Optimisation class for iterable function style |
|
Bayesian Optimisation class for vectorised function style |
|
Bayesian Optimisation class with automatic function signature detection |
Functions¶
|
|
|
|
|
Convert bounds like {'0': (lo,hi), '1': (lo,hi), ...} |
|
Wrap a vector/array objective f_vec(x) so it can be used by bayes_opt, |
|
Wrap a strict 2-D objective f_vec2d(X) for bayes_opt. |
|
Wrap an objective that might accept either a 1-D vector x (shape (d,)) |
Module Contents¶
- class pyuncertainnumber.opt.bo.BayesOpt_args_signature(f, design_bounds: dict, task, acquisition_function='UCB', num_explorations=100, num_iterations=100)¶
Bayesian Optimisation class with original function signature (arguments signature).
It requires the
design_boundto be a dictionary, e.g. {‘x1’: (0, 1), ‘x2’: (0, 1)}.- Parameters:
f (callable) – the target function to be optimised, should have individual function signature. See notes.
design_bounds (dict) – the bounds for the design space, e.g. {‘x1’: (0, 1), ‘x2’: (0, 1)}
task (str) – either ‘minimisation’ or ‘maximisation’
acquisition_function (str or callable, optional) – the acquisition function to be used, e.g. ‘UCB’, ‘EI’, ‘PI’. If None, defaults to ‘UCB’.
num_explorations (int, optional) – the number of initial exploration points. Defaults to 100.
num_iterations (int, optional) – the number of iterations to run the optimisation. Defaults to 100.
Note
Acquisition functions can be either a string (e.g. ‘UCB’, ‘EI’, ‘PI’) or a callable function. ‘UCB’ stands for Upper Confidence Bound, ‘EI’ for Expected Improvement, and ‘PI’ for Probability of Improvement. If a string is provided, the parameter for the acquisition function can be passed as an additional argument to the class constructor. For example, for ‘UCB’, you can pass a kappa value, and for ‘EI’ or ‘PI’, you can pass an xi value. For low-level controls, if a callable function is provided, it should already be parameterised.
About the function signature of $f$, by default it should be expecting individual arguments in the form of $f(x_0, x_1, ldots, x_n)$, often one needs to write a wrapper function to unpack the input arguments when working with a black-box model, which typically has vectorisation calling signature. Also, one can specify the xc_bound accordingly. When EpistemicDomain is used as a shortcut to specify the xc_bound, the keys will be automatically mapped to the corresponding arguments of the function.
Example
>>> import numpy as np >>> from pyuncertainnumber.opt.bo import BayesOpt_args_signature >>> def black_box_function(x): ... return np.exp(-(x - 2)**2) + np.exp(-(x - 6)**2 / 10) + 1 / (x**2 + 1) >>> bo = BayesOpt_args_signature( ... f=black_box_function, ... dimension=1, ... design_bounds={'x': (-2, 10)}, ... task='maximisation', ... num_explorations=3, ... num_iterations=20 ... ) >>> bo.run(verbose=True) >>> print(bo.optimal) # get the optimal parameters and target value
Implementation
This represents the original function signature. The range of the design space, defined in design_bound, is a dictionary mapping parameter names to their bounds. However, in later versions, such as the BayesOpt class, the design bounds can be specified as a list or 2D numpy array of shape (n, 2), and the function signature can be automatically detected.
example: >>> ed = EpistemicDomain(pba.I(-5, 5), pba.I(-5, 5)) >>> BayesOpt(f=foo, … design_bounds= ed.to_BayesOptBounds(func_signature=”arguments”), # the trick … task=’maximisation’, … num_explorations=3, … num_iterations=20, … )
- task¶
- num_explorations = 100¶
- num_iterations = 100¶
- design_bounds¶
- acquisition_function¶
- property f¶
return the function to be optimised
- parse_acq(acq, parameter=None)¶
parse the acquisition function
- Parameters:
acq (str or callable) – the acquisition function to be used. See notes above.
parameter (float, optional) – parameter for the acquisition function, e.g. kappa for UCB, xi for EI and PI
- get_results()¶
inspect the results, to save or not
- run(**kwargs)¶
run the Bayesian optimisation process.
- Parameters:
verbose (bool, optional) – whether to print the progress. Defaults to False. Use ‘verbose=True’ to see the progress.
**kwargs – additional low–level arguments to be passed to the BayesianOptimization constructor.
Example
>>> foo.run(verbose=True)
- property optimal: dict¶
return the optimal parameters and target value as a dictionary
- property optimal_xc: numpy.ndarray¶
return the optimal design points (xc)
- property optimal_target: numpy.ndarray¶
return the optimal target value f(xc*)
- class pyuncertainnumber.opt.bo.BayesOpt_iterable_signature(f, design_bounds: list[list[float]], dimension, task, acquisition_function='UCB', num_explorations=100, num_iterations=100)¶
Bases:
BayesOpt_args_signatureBayesian Optimisation class for iterable function style
See BayesOpt for additional details.
- class pyuncertainnumber.opt.bo.BayesOpt_vectorised_signature(f, design_bounds: list[list[float]], task, acquisition_function='UCB', num_explorations=100, num_iterations=100)¶
Bases:
BayesOpt_args_signatureBayesian Optimisation class for vectorised function style
See BayesOpt for additional details.
- class pyuncertainnumber.opt.bo.BayesOpt(f, design_bounds: list | numpy.ndarray, task, acquisition_function='UCB', num_explorations=100, num_iterations=100)¶
Bases:
BayesOpt_args_signatureBayesian Optimisation class with automatic function signature detection
The go to class for Bayesian Optimisation
- Parameters:
f (callable) – the target function to be optimised, it could be vectorised or iterable signature but NOT arguments signature. See notes.
design_bounds (list | np.ndarray) – the bounds for the design space, e.g. [[0, 1], [0, 1]]
task (str) – either ‘minimisation’ or ‘maximisation’
acquisition_function (str or callable, optional) – the acquisition function to be used, e.g. ‘UCB’, ‘EI’, ‘PI’. If None, defaults to ‘UCB’.
num_explorations (int, optional) – the number of initial exploration points. Defaults to 100.
num_iterations (int, optional) – the number of iterations to run the optimisation. Defaults to 100.
Note
Acquisition functions can be either a string (e.g. ‘UCB’, ‘EI’, ‘PI’) or a callable function. ‘UCB’ stands for Upper Confidence Bound, ‘EI’ for Expected Improvement, and ‘PI’ for Probability of Improvement. If a string is provided, the parameter for the acquisition function can be passed as an additional argument to the class constructor. For example, for ‘UCB’, you can pass a kappa value, and for ‘EI’ or ‘PI’, you can pass an xi value. For low-level controls, if a callable function is provided, it should already be parameterised.
About the function signature of $f$, by default it should be expecting individual arguments in the form of $f(x_0, x_1, ldots, x_n)$, often one needs to write a wrapper function to unpack the input arguments when working with a black-box model, which typically has vectorisation calling signature. Also, one can specify the xc_bound accordingly. When EpistemicDomain is used as a shortcut to specify the xc_bound, the keys will be automatically mapped to the corresponding arguments of the function.
The function is assumed to be a vectorised or iterable signature, indicating a f(x) with only one argument.
Example
>>> import numpy as np >>> from pyuncertainnumber.opt.bo import BayesOpt >>> def foo_vec(x): ... return x[:, 0] ** 3 + x[:, 1] + x[:, 2] >>> bo = BayesOpt( ... f=foo_vec, ... design_bounds=[(-2, 2), (-3, 3), (-1, 1)], ... task='maximisation', ... num_explorations=3, ... num_iterations=20 ... ) >>> bo.run(verbose=True) >>> print(bo.optimal) # get the optimal parameters and target value
Implementation
The range of the design space is defined by design_bounds, which is a 2D numpy array with shape (n, 2), where n is the number of parameters. For consistency, it is recommended to use the class EpistemicDomain.to_BayesOptBounds() to automatically take care of the format of the bounds.
example: >>> BayesOpt(f=foo_vec, … design_bounds= [(-2, 2), (-3, 3), (-1, 1)], … task=’maximisation’, … num_explorations=3, … num_iterations=20, … )
- pyuncertainnumber.opt.bo.check_argument_count(func)¶
- pyuncertainnumber.opt.bo.transform_func(fb, **kwargs)¶
- pyuncertainnumber.opt.bo.rekey_bounds_by_func(bounds_indexed: dict, func, *, allow_extras=False)¶
Convert bounds like {‘0’: (lo,hi), ‘1’: (lo,hi), …} into {‘param_name’: (lo,hi), …} using func’s signature.
- pyuncertainnumber.opt.bo.as_bayes_opt(f_vec, bounds_list, prefix='x')¶
Wrap a vector/array objective f_vec(x) so it can be used by bayes_opt, which calls f(**kwargs) with named scalar params.
- Parameters:
f_vec (callable) – Objective expecting a 1-D array-like x of length d. May also be vectorized and return a numpy array; we coerce to float.
bounds_list (list[tuple[float, float]]) – [(low_0, high_0), …, (low_{d-1}, high_{d-1})]
prefix (str) – Name prefix for parameters (x0, x1, …).
- Returns:
wrapped (callable(**kwargs) -> float)
pbounds (dict[str, tuple[float, float]])
names (list[str])
- pyuncertainnumber.opt.bo.as_bayes_opt_2d(f_vec2d, bounds_list, prefix='x')¶
Wrap a strict 2-D objective f_vec2d(X) for bayes_opt.
- Parameters:
f_vec2d (callable) –
Objective expecting a 2-D array X of shape (m, d) and returning an array of shape (m,) (or something squeezable to that). Example:
def f_vec2d(X): return X[:, 0]**3 + X[:, 1] + X[:, 2]
bounds_list (list[tuple[float, float]]) – Bounds in order for each of the d dimensions.
prefix (str) – Parameter name prefix for kwargs: x0, x1, …
- Returns:
wrapped (callable(**kwargs) -> float) – Callable compatible with BayesianOptimization (single-point evaluation).
pbounds (dict[str, tuple[float, float]]) – Name→bounds mapping for bayes_opt.
names (list[str]) – The ordered parameter names used by wrapped.
- pyuncertainnumber.opt.bo.as_bayes_opt_auto(f_any, bounds_list, prefix='x', prefer_2d=False)¶
Wrap an objective that might accept either a 1-D vector x (shape (d,)) or a strict 2-D matrix X (shape (m, d), here m=1 per BO call).
The wrapper auto-detects the expected shape on the first call by trying one shape then the other, caches the mode, and always returns a scalar float.
- Parameters:
f_any (callable) –
- Objective. Examples:
def f_vec(x: np.ndarray): return x[0]**3 + x[1] + x[2] # expects (d,)
def f_mat(X: np.ndarray): return X[:,0]**3 + X[:,1] + X[:,2] # expects (m,d)->(m,)
bounds_list (list[tuple[float, float]]) – [(low_0, high_0), …, (low_{d-1}, high_{d-1})]
prefix (str) – Name prefix for kwargs (e.g., x0, x1, …).
prefer_2d (bool) – If True, try (1, d) first, else try (d,) first. Useful when you expect strict 2-D but still want auto fallback.
- Returns:
wrapped (callable(**kwargs) -> float)
pbounds (dict[str, tuple[float, float]])
names (list[str])