Quickstart Guide#
This guide will get you started with JAXSR in a few minutes.
Installation#
pip install jaxsr
Basic Usage#
1. Import and Prepare Data#
import jax.numpy as jnp
import numpy as np
from jaxsr import BasisLibrary, SymbolicRegressor
# Generate sample data
np.random.seed(42)
X = np.random.randn(100, 2)
y = 2.5 * X[:, 0] + 1.2 * X[:, 0] * X[:, 1] - 0.8 * X[:, 1]**2
X = jnp.array(X)
y = jnp.array(y)
2. Build a Basis Library#
The basis library defines the candidate functions to consider:
library = (BasisLibrary(n_features=2, feature_names=["x", "y"])
.add_constant() # 1
.add_linear() # x, y
.add_polynomials(max_degree=3) # x^2, x^3, y^2, y^3
.add_interactions() # x*y
)
print(f"Library has {len(library)} basis functions")
3. Fit the Model#
model = SymbolicRegressor(
basis_library=library,
max_terms=5,
strategy="greedy_forward",
information_criterion="bic",
)
model.fit(X, y)
4. Examine Results#
# Expression
print(f"Discovered: {model.expression_}")
# Metrics
print(f"R² = {model.metrics_['r2']:.4f}")
print(f"MSE = {model.metrics_['mse']:.6f}")
# Predict
y_pred = model.predict(X)
Using the Convenience Function#
For quick exploration, use fit_symbolic:
from jaxsr import fit_symbolic
model = fit_symbolic(
X, y,
feature_names=["x", "y"],
max_terms=5,
max_poly_degree=3,
)
print(model.expression_)
Adding Constraints#
Incorporate domain knowledge:
from jaxsr import Constraints
constraints = (Constraints()
.add_bounds("y", lower=0) # Non-negative output
.add_sign_constraint("x", sign="positive") # Positive coefficient
)
model = SymbolicRegressor(
basis_library=library,
constraints=constraints,
)
model.fit(X, y)
Exploring the Pareto Front#
View the trade-off between complexity and accuracy:
for result in model.pareto_front_:
print(f"Complexity {result.complexity}: MSE={result.mse:.4f}")
print(f" {result.expression()}")
Exporting Models#
# SymPy expression
sympy_expr = model.to_sympy()
# LaTeX
latex = model.to_latex()
# Pure NumPy callable (no JAX dependency)
predict_fn = model.to_callable()
y_pred = predict_fn(np.array(X))
# Save/load
model.save("model.json")
loaded = SymbolicRegressor.load("model.json")
Selection Strategies#
Choose the appropriate strategy for your problem:
Strategy |
Best For |
Speed |
|---|---|---|
|
Default, most problems |
Fast |
|
Starting with many terms |
Fast |
|
Small libraries (<20) |
Slow |
|
Large libraries, screening |
Medium |
model = SymbolicRegressor(
basis_library=library,
strategy="lasso_path", # or "exhaustive", "greedy_backward"
)
Uncertainty Quantification#
JAXSR provides several UQ methods. Since models are linear-in-parameters (y = Phi @ beta), classical OLS inference applies directly.
Prediction Intervals#
# 95% prediction interval for new observations
y_pred, lower, upper = model.predict_interval(X_new, alpha=0.05)
# 95% confidence band on the mean response E[y|x]
y_pred, conf_lo, conf_hi = model.confidence_band(X_new, alpha=0.05)
# Confidence intervals for each coefficient
intervals = model.coefficient_intervals(alpha=0.05)
for name, (est, lo, hi, se) in intervals.items():
print(f" {name}: {est:.4f} [{lo:.4f}, {hi:.4f}] (SE={se:.4f})")
# Estimated noise level
print(f"sigma = {model.sigma_:.4f}")
Bayesian Model Averaging#
Average predictions across multiple models weighted by information criteria:
# BMA prediction with intervals
y_pred, lower, upper = model.predict_bma(X_new, criterion="bic")
# Inspect model weights
from jaxsr import BayesianModelAverage
bma = BayesianModelAverage(model, criterion="bic")
for expr, weight in bma.weights.items():
print(f" {weight:.3f} {expr}")
Conformal Prediction#
Distribution-free prediction intervals with coverage guarantees:
# Jackknife+ (uses training data, no separate calibration set)
y_pred, lower, upper = model.predict_conformal(X_new, method="jackknife+")
# Split conformal (requires held-out calibration data)
y_pred, lower, upper = model.predict_conformal(
X_new, method="split", X_cal=X_cal, y_cal=y_cal
)
Ensemble and Bootstrap#
# Pareto front ensemble: how predictions vary across model complexities
result = model.predict_ensemble(X_new)
print(f"Ensemble mean: {result['y_mean']}")
print(f"Ensemble std: {result['y_std']}")
# Residual bootstrap (no Gaussian assumption)
from jaxsr import bootstrap_predict, bootstrap_coefficients
result = bootstrap_predict(model, X_new, n_bootstrap=1000, seed=42)
print(f"Bootstrap CI: [{result['lower']}, {result['upper']}]")
Visualization#
from jaxsr.plotting import (
plot_prediction_intervals,
plot_coefficient_intervals,
plot_bma_weights,
)
# Fan chart with confidence and prediction bands
plot_prediction_intervals(model, X, y)
# Forest plot of coefficient CIs
plot_coefficient_intervals(model)
# BMA weight bar chart
plot_bma_weights(model)
Next Steps#
See the Tutorial for application-specific tutorials
Read the API Reference for detailed documentation
Check the Literature Review for background