mixle.doe.optimizer module¶
Ask-tell Bayesian-optimization interface for mixle.doe (WS-E).
A small stateful optimizer object for the common human/experiment-in-the-loop workflow, where the objective is expensive or physical and evaluated outside the loop:
opt = BayesianOptimizer(bounds, acq="ei")
for _ in range(n):
x = opt.ask() # next point(s) to evaluate
y = run_experiment(x) # ... done by the caller, however slow
opt.tell(x, y) # feed the result back
opt.best # best (x, y) so far
It holds the observation history and delegates proposals to the functional API
(mixle.doe.bayesopt): the first n_init asks come from a space-filling Latin-hypercube
design (a GP needs data before it is useful), after which asks are GP-acquisition proposals
(ask(q>1) returns a kriging-believer batch). Constrained and multi-objective problems keep their
functional drivers (constrained_minimize / multi_minimize).
Every point ask() returns is tracked as pending until a matching BayesianOptimizer.tell()
call resolves it – see that method’s docstring for the exact match / duplicate / unsolicited policy.
- class BayesianOptimizer(bounds, *, acq='ei', acq_kwargs=None, maximize=False, n_init=None, xi=0.0, n_candidates=512, fit_kwargs=None, seed=None)[source]
Bases:
objectStateful ask-tell wrapper around the GP Bayesian-optimization loop.
askproposes the next point (or a batch),tellrecords evaluated observations, andbestreturns the incumbent. Minimizes by default; setmaximize=Trueto maximize. The acquisition is selected byacq("ei"/"pi"/"ucb"or any registered name / callable) with per-acquisition parameters inacq_kwargs.ask()tracks every point it returns as pending (asked, not yet told) until a matchingtell()call resolves it. A second, overlappingask()– issued before an earlier one’s points are told, as in a parallel/async evaluation campaign – folds those still-pending points into the surrogate fit as fantasized (kriging-believer) observations, the same mechanismpropose_batch()already uses to keep a single batch’s own picks apart, so acquisition is steered away from proposing them again (MXR-080-0188).- Parameters:
- property x: ndarray
Return the observed points as an
(N, d)array.
- property y: ndarray
Return the observed objective values as an
(N,)array.
- property n_observations: int
Return the number of recorded observations.
- property pending: ndarray
Return currently pending (asked, not yet told) points as a
(P, d)array.
- property n_pending: int
Return the number of currently pending (asked, not yet told) points.
- property best: BayesOptResult
Return the incumbent (best observed point) as a
BayesOptResult.
- ask(q=1)[source]
Return the next point to evaluate as a
(d,)array, or a(q, d)batch whenq > 1.The first
n_initpoints come from a space-filling design; subsequent points are GP acquisition proposals (a kriging-believer batch whenq > 1). Every returned point is tracked as pending untiltell()resolves it; a second, overlappingask()before anytell()folds still-pending points into the GP fit as fantasized observations so it is steered away from proposing them again (see the class docstring, MXR-080-0188).This call is atomic: if it raises (e.g. a GP proposal attempted with zero observations), no internal state changes, so a failed call is always safe to retry.
- tell(x, y)[source]
Record one or more evaluated observations; returns
selffor chaining.xis a(d,)point or(m, d)batch andythe matching scalar or(m,)values. Every point must be finite and withinbounds, and every outcome must be finite – a NaN/Inf in either would otherwise poison every downstream GP fit and acquisition score silently. Every point must also match a currently pending proposal, i.e. one this same optimizer’s ownask()actually returned and that has not already been told:a point that was never returned by
ask()(an unsolicited observation) is rejected – this is almost always a caller bug (wrong array, a stale point from a different optimizer), so it is rejected by default rather than silently accepted;a point that was already told (whether repeated within this same call or told in a previous one) is rejected as a duplicate –
tell()is write-once per point, there is no “update an existing observation” path.
(MXR-080-0188.) Raises
ValueErrorfor any of the above. Validation covers the whole batch before anything is applied, so a batch that is only partly invalid never half-applies.