jaxsr.acquisition#
Active Learning Acquisition Functions for JAXSR.
Provides a composable framework for design-of-experiment (DOE) and Bayesian optimization-style active learning on top of JAXSR symbolic regression models.
Because JAXSR models are linear-in-parameters (y = Phi @ beta), we have closed-form expressions for prediction variance, leverage, and coefficient covariance. This means acquisition functions that rely on posterior uncertainty are exact—no GP approximations needed.
Classes#
- AcquisitionFunction
Abstract base class. Subclasses implement
score().- PredictionVariance
Pure exploration: sigma^2(x) from OLS posterior.
- ConfidenceBandWidth
Width of the confidence band on E[y|x].
- EnsembleDisagreement
Standard deviation across Pareto-front model predictions.
- BMAUncertainty
Bayesian Model Averaging uncertainty (within + between variance).
- ModelDiscrimination
Maximum pairwise disagreement among top Pareto models.
- UCB / LCB
Upper / Lower Confidence Bound: y_hat +/- kappa * sigma.
- ExpectedImprovement
EI(x) = E[max(0, f_best - y_hat(x))] (Gaussian).
- ProbabilityOfImprovement
PI(x) = P(y(x) < f_best - xi).
- ThompsonSampling
Draw beta ~ N(beta_hat, Cov), score = sampled prediction.
- AOptimal
Minimize tr(Cov) after adding a candidate point.
- DOptimal
Maximize det(Phi^T Phi) after adding a candidate point.
- Composite
Weighted combination of acquisition functions.
- ActiveLearner
Orchestrator that combines candidate generation, scoring, batch selection, and the iterative update loop.
Example
>>> from jaxsr.acquisition import ActiveLearner, UCB, ExpectedImprovement
>>> learner = ActiveLearner(model, bounds=[(0, 5)], acquisition=UCB(kappa=2.0))
>>> result = learner.suggest(n_points=5)
>>> # run experiments on result.points ...
>>> learner.update(result.points, y_new)
- class jaxsr.acquisition.AcquisitionResult(points: ~jax.jaxlib._jax.Array, scores: ~jax.jaxlib._jax.Array, acquisition: str, metadata: dict[str, ~typing.Any] = <factory>)#
Bases:
objectResult returned by
ActiveLearner.suggest().- points#
Suggested points, shape
(n_points, n_features).- Type:
jnp.ndarray
- scores#
Acquisition score for each suggested point.
- Type:
jnp.ndarray
- acquisition#
Name of the acquisition function used.
- Type:
str
- metadata#
Extra info (e.g.
y_pred,sigma, batch diversity stats).- Type:
dict
- points: Array#
- scores: Array#
- acquisition: str#
- metadata: dict[str, Any]#
- class jaxsr.acquisition.BatchStrategy(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
EnumStrategies for selecting diverse batches.
- GREEDY = 'greedy'#
- PENALIZED = 'penalized'#
- KRIGING_BELIEVER = 'kriging_believer'#
- D_OPTIMAL = 'd_optimal'#
- class jaxsr.acquisition.AcquisitionFunction#
Bases:
ABCAbstract base for all acquisition functions.
Subclasses must implement
score(). The convention is higher score = more desirable to sample.Supports composition via
+and scalar*:combined = 0.7 * UCB(kappa=2) + 0.3 * PredictionVariance()
- abstract score(X_candidates: jnp.ndarray, model: SymbolicRegressor) jnp.ndarray#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- property name: str#
- class jaxsr.acquisition.PredictionVariance#
Bases:
AcquisitionFunctionScore = prediction variance sigma^2(x).
For an OLS model, the prediction variance at a new point x is
\[\sigma^2(x) = \hat\sigma^2 \, \varphi(x)^\top (\Phi^\top\Phi)^{-1} \varphi(x)\]where \(\hat\sigma^2\) is the unbiased noise variance estimate.
When to use: Default choice for pure exploration. Sample where the model is least certain about the mean prediction. Good for improving model accuracy uniformly across the input space.
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ConfidenceBandWidth(alpha: float = 0.05)#
Bases:
AcquisitionFunctionScore = width of the
1-alphaconfidence band on E[y|x].The width is \(2 \, t_{\alpha/2,\nu} \, \sigma(x)\).
- Parameters:
alpha (float) – Significance level (default 0.05 for 95% band).
use (**When to)
target). (confidence band specifically (e.g. you have a coverage)
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.EnsembleDisagreement#
Bases:
AcquisitionFunctionScore = standard deviation across Pareto-front model predictions.
This captures structural (model-form) uncertainty: where do models of different complexity disagree?
When to use: When you suspect model misspecification and want to identify regions where the choice of model complexity matters most. Helps resolve “which model is right?” rather than “how noisy is the data?”.
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.BMAUncertainty(criterion: str = 'bic', top_k: int | None = None)#
Bases:
AcquisitionFunctionScore = BMA posterior standard deviation.
Combines within-model variance (noise) and between-model variance (structural uncertainty) via IC-weighted Bayesian Model Averaging.
- Parameters:
criterion (str) – Information criterion for weights (
"bic"or"aic").top_k (int or None) – Number of top models to include in the average.
use (**When to)
and (Use when you want a single number that accounts for both noise)
than (model selection uncertainty. More expensive)
:param
PredictionVariancebecause it evaluates multiple models.:- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ModelDiscrimination(top_k: int | None = None)#
Bases:
AcquisitionFunctionScore = maximum pairwise disagreement among Pareto-front models.
For each candidate x, computes the max absolute difference between any pair of Pareto-front model predictions. Points with high scores are the most informative for deciding which model structure is correct.
- Parameters:
top_k (int or None) – Only compare the top_k Pareto models.
Noneuses all.use (**When to)
is (correct. Particularly useful in early stages when model structure)
is
uncertain. (still)
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ModelMin#
Bases:
AcquisitionFunctionScore = -y_hat(x). Finds the minimum of the surrogate.
When to use: Pure exploitation. You fully trust the model and want to sample at its predicted optimum. Combine with an exploration term (e.g.
0.8 * ModelMin() + 0.2 * PredictionVariance()) to avoid getting stuck.- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ModelMax#
Bases:
AcquisitionFunctionScore = y_hat(x). Finds the maximum of the surrogate.
When to use: Pure exploitation when maximising the response.
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.UCB(kappa: float = 2.0)#
Bases:
AcquisitionFunctionUpper Confidence Bound.
\[\text{UCB}(x) = \hat y(x) + \kappa \, \sigma(x)\]- Parameters:
kappa (float) – Exploration weight. Larger values favour exploration. A common starting point is
kappa=2.0.use (**When to)
exploration-exploitation (The kappa parameter directly controls the)
balance.
0 (- kappa =)
2 (- kappa ~)
3 (- kappa >)
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.LCB(kappa: float = 2.0)#
Bases:
AcquisitionFunctionLower Confidence Bound.
\[\text{LCB}(x) = -\hat y(x) + \kappa \, \sigma(x)\]Score convention: higher is more desirable, so the sign of the predicted mean is flipped. Minimising y corresponds to maximising
-y_hat + kappa * sigma.- Parameters:
kappa (float) – Exploration weight (same semantics as
UCB).use (**When to)
UCB. (Mirror image of)
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ExpectedImprovement(y_best: float | None = None, xi: float = 0.01, minimize: bool = True)#
Bases:
AcquisitionFunctionExpected Improvement over the current best.
\[\text{EI}(x) = (\hat y_\text{best} - \hat y(x))\, \Phi(z) + \sigma(x)\,\phi(z), \quad z = \frac{\hat y_\text{best} - \hat y(x) - \xi}{\sigma(x)}\]for minimisation (flip signs for maximisation).
- Parameters:
y_best (float or None) – Current best observed value. If
None, the best value from the training set is used automatically.xi (float) – Jitter for encouraging exploration (default 0.01).
minimize (bool) – If
True(default), seek points that reduce y. IfFalse, seek points that increase y.use (**When to)
(predicted (balances exploration (high sigma) and exploitation)
UCB. (improvement over best). Less sensitive to hyperparameters than)
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ProbabilityOfImprovement(y_best: float | None = None, xi: float = 0.01, minimize: bool = True)#
Bases:
AcquisitionFunctionProbability of improving over the current best.
\[\text{PI}(x) = \Phi\!\left( \frac{\hat y_\text{best} - \hat y(x) - \xi}{\sigma(x)} \right)\]- Parameters:
y_best (float or None) – Current best observed value.
None= auto from training data.xi (improvement. Tends to be more exploitative than EI for the same) – Improvement threshold (default 0.01).
minimize (bool) – If
True, seek reduction in y.use (**When to)
of (*probability* of beating a threshold rather than the magnitude)
xi
magnitude. (because it ignores improvement)
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ThompsonSampling(minimize: bool = True, seed: int | None = None)#
Bases:
AcquisitionFunctionThompson Sampling via posterior coefficient draw.
Draws \(\beta \sim \mathcal{N}(\hat\beta, \text{Cov}(\hat\beta))\) and scores each candidate with the sampled model.
- Parameters:
minimize (bool) – If
True, score = -y_sampled (prefer smaller predicted y).seed (int or None) – Random seed for the posterior draw.
use (**When to)
posterior (Each call to score() draws a different model from the)
:param : :param so repeated calls produce diverse batches without explicit: :param diversification. Theoretically elegant; matches Bayes-optimal: :param one-step-ahead strategy.:
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.AOptimal#
Bases:
AcquisitionFunctionA-Optimal design: reduce average parameter uncertainty.
Score for adding candidate x is the reduction in \(\text{tr}(\text{Cov}(\hat\beta))\).
\[\Delta\text{tr} = \frac{ \varphi(x)^\top (\Phi^\top\Phi)^{-1} \text{Cov}(\hat\beta) (\Phi^\top\Phi)^{-1} \varphi(x) }{1 + \varphi(x)^\top (\Phi^\top\Phi)^{-1} \varphi(x)}\]When to use: When your goal is to tighten the confidence intervals on all coefficients. Good for model building where every parameter matters (e.g. reporting a physics equation).
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.DOptimal#
Bases:
AcquisitionFunctionD-Optimal design: maximise information gain.
Score = leverage \(h(x) = \varphi(x)^\top (\Phi^\top\Phi)^{-1} \varphi(x)\), which is proportional to the increase in \(\det(\Phi^\top\Phi)\) from adding the point.
When to use: When you want maximum information per experiment. Classic choice for building precise models with minimal data. Tends to place points at the “edges” of the design space.
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.Composite(functions: list[tuple[float, AcquisitionFunction]])#
Bases:
AcquisitionFunctionWeighted combination of acquisition functions.
Typically created via operator overloading rather than directly:
acq = 0.7 * UCB(kappa=2) + 0.3 * PredictionVariance()
Each component is scored independently and the weighted sum is returned after min-max normalisation of each component.
- functions#
- Type:
list of (weight, AcquisitionFunction)
- property name: str#
- score(X_candidates, model)#
Score each candidate (higher = more desirable).
- Parameters:
X_candidates (jnp.ndarray, shape (n_candidates, n_features)) – Candidate points to evaluate.
model (SymbolicRegressor) – Fitted symbolic regression model.
- Returns:
scores
- Return type:
jnp.ndarray, shape (n_candidates,)
- class jaxsr.acquisition.ActiveLearner(model: SymbolicRegressor, bounds: list[tuple[float, float]], acquisition: AcquisitionFunction, n_candidates: int = 1000, candidate_method: str = 'lhs', random_state: int | None = None)#
Bases:
objectOrchestrator for iterative active learning / DOE.
Combines candidate generation, acquisition scoring, batch selection, and model updating into a single workflow.
- Parameters:
model (SymbolicRegressor) – A fitted model to improve.
bounds (list of (float, float)) – Input bounds
[(lo, hi), ...]for each feature.acquisition (AcquisitionFunction) – The acquisition function (or composite) to use for scoring.
n_candidates (int) – Number of space-filling candidates to generate internally.
candidate_method (str) – Candidate generation method:
"lhs"(default),"sobol","halton", or"random".random_state (int or None) – Seed for reproducibility.
- history_X#
Points suggested at each iteration.
- Type:
list of jnp.ndarray
- history_y#
Observations received at each iteration.
- Type:
list of jnp.ndarray
- iteration#
Number of suggest-update cycles completed.
- Type:
int
Examples
>>> learner = ActiveLearner(model, bounds=[(0, 5)], ... acquisition=UCB(kappa=2)) >>> for _ in range(10): ... result = learner.suggest(n_points=3) ... y_new = oracle(result.points) ... learner.update(result.points, y_new)
- suggest(n_points: int = 5, batch_strategy: str = 'greedy', min_distance: float = 0.01, candidates: Array | None = None) AcquisitionResult#
Suggest the next batch of points to evaluate.
- Parameters:
n_points (int) – Number of points to return.
batch_strategy (str) – How to select a batch:
"greedy"(top-k by score),"penalized"(top-1, penalise nearby, repeat),"kriging_believer"(top-1, fantasise observation, repeat),"d_optimal"(select batch maximising det(Phi^T Phi)).min_distance (float) – Minimum normalised distance from training data.
candidates (jnp.ndarray, optional) – Pre-specified candidate pool. If
None, candidates are generated internally.
- Returns:
With
.points,.scores, and.metadata.- Return type:
- update(X_new: Array, y_new: Array, refit: bool = True) None#
Add new observations and refit the model.
- Parameters:
X_new (jnp.ndarray) – New input points.
y_new (jnp.ndarray) – Observed responses.
refit (bool) – If
True, rerun full feature selection. IfFalse, keep the same basis terms and refit coefficients.
- converged(tol: float = 0.001, window: int = 3, metric: str = 'mse') bool#
Check whether model improvement has stalled.
- Parameters:
tol (float) – Minimum relative improvement to consider “not converged”.
window (int) – Number of recent iterations to compare.
metric (str) – Metric to track:
"mse"or"r2".
- Returns:
Trueif improvement over the last window iterations is below tol.- Return type:
bool
- property best_y: float#
Best observed y in the training set.
- property best_X: Array#
Input corresponding to the best observed y.
- property n_observations: int#
Total number of observations in the training set.
- jaxsr.acquisition.suggest_points(model: SymbolicRegressor, bounds: list[tuple[float, float]], acquisition: AcquisitionFunction, n_points: int = 5, batch_strategy: str = 'greedy', n_candidates: int = 1000, random_state: int | None = None) AcquisitionResult#
One-shot convenience: suggest points without creating an ActiveLearner.
- Parameters:
model (SymbolicRegressor) – Fitted model.
bounds (list of (float, float)) – Feature bounds.
acquisition (AcquisitionFunction) – Acquisition function to use.
n_points (int) – Number of points.
batch_strategy (str) – Batch strategy.
n_candidates (int) – Candidate pool size.
random_state (int or None) – Seed.
- Return type: