Skip to content

API Reference

ebf.EBF

Elliptical Basis Function interpolation model.

Parameters

n_nodes : int Number of EBF nodes. basis : str, optional Basis function name. See ebf.BASIS_FUNCTIONS for available options. Default is 'multiquadric'. eps : float, optional Numerical stability offset for basis functions that need it. Default is 1e-8.

Examples

import numpy as np import ebf model = ebf.EBF(n_nodes=8) X = np.linspace(0, 2 * np.pi, 30).reshape(-1, 1) y = np.sin(X).ravel() model.fit(X, y, steps=5000) y_pred = model.predict(X) nodes = model.get_nodes()

__init__(n_nodes, basis=DEFAULT_BASIS, eps=1e-08)

fit(X, y=None, *, steps=60000, lr=0.01, var_weight=0.2, ellipsoid_weight=0.0, loss_type='rmse', huber_delta='auto', tukey_c='auto', val_fraction=0.0, patience=10, verbose=True, loss_threshold=None, seed=None)

Train the model on input data.

Accepts either separate arrays X and y, or a single combined array where the last column is the output variable.

Parameters

X : array-like, shape (n_points, n_dims) or (n_points, n_dims+1) Input features. If y is None, the last column of X is treated as the output variable. y : array-like, shape (n_points,), optional Output variable. Required when X contains only input features. steps : int, optional Number of optimizer iterations. Default is 60000. lr : float, optional Initial learning rate for Adam. Default is 0.01. var_weight : float, optional Regularization strength for node spread (see ADR-002). Default is 0.2. ellipsoid_weight : float, optional Ellipsoid shape penalty strength (see ADR-011). Penalizes the mean squared Frobenius norm of the per-node ellipsoid factors L, keeping node influence zones small and round for a smoother surface. Default is 0.0 (penalty disabled). loss_type : str, optional 'rmse' (default), 'huber', or 'tukey'. Huber gives outliers linear (reduced) weight; Tukey biweight is redescending — residuals beyond the rejection point exert zero pull on the surface, so gross outliers are effectively discarded. See ADR-009/013/014. huber_delta : 'auto' or float, optional Huber loss threshold in scaled data space. Default is 'auto' (ADR-013): the threshold is recalibrated every 100 steps from the current residual spread (a robust MAD estimate), so roughly the largest ~18% of residuals get linear, outlier-resistant treatment as the fit tightens. Pass a float to fix the threshold instead. Only used when loss_type='huber'. tukey_c : 'auto' or float, optional Tukey biweight rejection point in scaled data space. Default is 'auto' (ADR-014, recommended): 4.685 * sigma with the same MAD recalibration, which anneals from an effectively quadratic start — important because the Tukey loss is non-convex and a fixed small c can reject most points at initialization and stall training. Only used when loss_type='tukey'. val_fraction : float, optional Fraction of points held out as a validation set for early stopping (see ADR-012). Default is 0.0 — no split, identical to previous behavior. When > 0, the validation loss is evaluated every 100 steps, training stops once it has not improved for patience consecutive evaluations, and the weights from the best-validation step are restored. Replaces guessing steps on noisy data, where training loss keeps falling while the model memorizes noise. Only reliable with ~50+ points — below that the held-out loss is too noisy to give a stable stopping signal (a UserWarning is issued); prefer regularization (var_weight, ellipsoid_weight, loss_type='huber') on small datasets. patience : int, optional Number of consecutive validation evaluations without improvement before stopping. Default is 10 (i.e. 1000 steps). Only used when val_fraction > 0. verbose : bool, optional Print training progress every 100 steps. Default is True. loss_threshold : float or None, optional Stop early when the training loss drops to or below this value. None disables. Default is None. seed : int or None, optional Random seed for reproducible weight initialization and validation split. None (default) is non-deterministic.

Returns

self The fitted model (allows method chaining).

Notes

After fitting, the per-step training history is available as self.history_ — an (n_steps_run, 2) array with columns (step, loss), useful for convergence plots and tuning var_weight / loss_threshold. When val_fraction > 0 a third val_loss column is added (NaN except at evaluation steps).

predict(X)

Predict output values at new input points.

Parameters

X : array-like, shape (n_points, n_dims) Input points in original (unscaled) space.

Returns

Y : numpy.ndarray, shape (n_points,) Predicted output in original space.

get_nodes()

Return node positions in original (unscaled) space.

Returns

nodes : numpy.ndarray, shape (n_nodes, n_dims) Node center positions in the original data space.

get_ellipsoids()

Return per-node ellipsoid matrices in original (unscaled) space.

Each node's influence region is the quadratic form r_i^2 = (x - v_i)^T A_i (x - v_i), where v_i is the node position from :meth:get_nodes. This method returns the A_i expressed in the original data units, so the two can be used together directly (e.g. to draw iso-distance ellipses on a plot).

The model trains on standardized data, where delta_scaled = S * delta with S = diag(Scale[:-1]). Since r^2 is invariant, the original-space matrix is S A S.

Returns

A : numpy.ndarray, shape (n_nodes, n_dims, n_dims) Symmetric positive-definite ellipsoid matrices. Small eigenvalues correspond to long ellipsoid axes (slow decay in that direction), large eigenvalues to short axes.

Examples

Semi-axis lengths and orientation of the r = 1 contour for node i, via the eigendecomposition A = Q L Q^T::

A = model.get_ellipsoids()[i]
eigvals, eigvecs = np.linalg.eigh(A)
semi_axes = 1.0 / np.sqrt(eigvals)   # along columns of eigvecs
See Also

get_nodes : the matching node center positions.

save(path, filename='ebf-model')

Save model to a checkpoint directory.

Parameters

path : str Directory for checkpoint files. filename : str, optional Checkpoint filename stem. Default is 'ebf-model'.

Returns

file : str Checkpoint file stem (pass to EBF.load()).

load(file) classmethod

Restore an EBF model from a checkpoint.

Parameters

file : str Checkpoint file stem as returned by save().

Returns

model : EBF A fitted EBF instance ready for predict() and get_nodes().

Functional API

The functional API is the original interface, kept for backwards compatibility. For new code, prefer the class API above.

ebf.train.run(data, n_nodes, basis=DEFAULT_BASIS, eps=1e-08, var_weight=0.2, ellipsoid_weight=0.0, loss_type='rmse', huber_delta='auto', tukey_c='auto', path='./', filename='my-model', train_steps=60000, start=0.01, loss_threshold=None, seed=None, verbose=True, return_history=False, val_fraction=0.0, patience=10)

Train an EBF model and save a checkpoint.

Parameters

data : (n_points, n_dims+1) array — last column is the output variable n_nodes : int — number of EBF nodes basis : str — basis function name (default: 'multiquadric') eps : float — numerical stability offset for basis functions (default: 1e-8) var_weight : float — regularization strength for node spread (default: 0.2) ellipsoid_weight : float — ellipsoid shape penalty strength; penalizes the mean squared Frobenius norm of the per-node ellipsoid factors L, keeping node influence zones small and round for a smoother surface. 0.0 (default) disables the penalty; see ADR-011 loss_type : str — 'rmse' (default), 'huber' (robust — outliers get linear treatment; ADR-009/013), or 'tukey' (redescending — outliers beyond the rejection point exert zero pull; ADR-014) huber_delta : 'auto' or float — Huber threshold in scaled data space. 'auto' (default) recalibrates the threshold every 100 steps from the current residual spread so roughly the largest ~18% of residuals get linear (outlier-resistant) treatment; a float fixes the threshold instead. See ADR-013 tukey_c : 'auto' or float — Tukey biweight rejection point in scaled data space; residuals beyond it are ignored entirely. 'auto' (default, recommended) tracks the residual noise floor at 4.685 * sigma, annealing from an effectively quadratic start. See ADR-014 path : str — directory for checkpoint files (default: './') filename : str — checkpoint filename stem (default: 'my-model') train_steps : int — number of optimizer steps (default: 60000) start : float — initial learning rate (default: 0.01) loss_threshold : float or None — stop early when the training loss drops to or below this value. None disables (default: None) seed : int or None — random seed for reproducible weight initialization and validation split. None (default) is non-deterministic verbose : bool — print scaling info and training progress (default: True) return_history : bool — when True, also return the per-step training history as a fourth value (default: False) val_fraction : float — fraction of points held out as a validation set for early stopping (default: 0.0 = disabled, identical to previous behavior). When > 0, the validation loss is evaluated every 100 steps, training stops once it has not improved for patience consecutive evaluations, and the weights from the best-validation step are restored. Only reliable with ~50+ points — below that the held-out loss is too noisy to give a stable stopping signal (a UserWarning is issued); prefer regularization on small datasets. See ADR-012 patience : int — number of consecutive validation evaluations without improvement before stopping (default: 10, i.e. 1000 steps). Only used when val_fraction > 0

Returns

Scale : (n_dims+1,) — 1/std per column Offset : (n_dims+1,) — mean per column file : str — checkpoint file stem for use with predict.run_points() history : (n_steps_run, 2) ndarray — (step, loss) per step; only returned when return_history=True. When val_fraction > 0 a third val_loss column is added (NaN except at evaluation steps)

ebf.predict.run_points(points, Scale=None, Offset=None, file=None)

Evaluate the trained EBF model at new input points.

Parameters

points : (n_points, n_dims) — input points in original (unscaled) space Scale : (n_dims+1,) array or None — 1/std per column. None (default) reads the value stored in the checkpoint's JSON sidecar by train.run() Offset : (n_dims+1,) array or None — mean per column. None (default) reads the sidecar value file : str — checkpoint file stem returned by train.run() (required)

Returns

Y : (n_points,) — predicted output in original space Nodes : (n_nodes, n_dims) — node positions in original space

Visualization Utilities

ebf.viz.convergence_plot(history, ax=None, *, log_scale=True, loss_threshold=None)

Training (and validation) loss curve from a training history.

Parameters

history : array-like, shape (n_steps, 2) or (n_steps, 3), or ebf.EBF Training history with columns (step, loss) — either EBF.history_, the fourth return value of run(..., return_history=True), or a fitted EBF instance (its history_ attribute is used). Histories from a run with val_fraction > 0 have a third val_loss column (NaN except at evaluation steps), plotted as a second curve. ax : matplotlib.axes.Axes, optional Axes to draw on. A new figure is created when None. log_scale : bool, optional Plot the loss on a logarithmic axis. Default True — the loss typically spans orders of magnitude over a run. loss_threshold : float, optional Draw the early-stopping threshold as a horizontal reference line (pass the same value given to fit() / run()).

Returns

fig : matplotlib.figure.Figure ax : matplotlib.axes.Axes

ebf.viz.correlation_plot(y_true, y_pred, ax=None, *, c=None, cmap=None, norm=None)

Scatter plot of data vs prediction with 1:1 line and R².

Parameters

y_true : array-like, shape (n,) Observed values. y_pred : array-like, shape (n,) Predicted values. ax : matplotlib.axes.Axes, optional Axes to draw on. A new figure is created when None. c : array-like, shape (n,), optional Per-point values to color the markers by (e.g. absolute error). Uses the flat style colour when None. cmap, norm : optional Colormap and normalization applied to c.

Returns

fig : matplotlib.figure.Figure ax : matplotlib.axes.Axes

ebf.viz.residual_plot(y_true, y_pred, ax=None, *, c=None, cmap=None, norm=None)

Scatter plot of residuals against predictions with a zero line.

Complements :func:correlation_plot: structure in this plot that the correlation chart compresses along its 1:1 line becomes visible here — a curve means systematic bias (too few nodes or over-smoothing), a funnel means the error scales with the output level, and outliers stand apart from the cloud.

Parameters

y_true : array-like, shape (n,) Observed values. y_pred : array-like, shape (n,) Predicted values. ax : matplotlib.axes.Axes, optional Axes to draw on. A new figure is created when None. c : array-like, shape (n,), optional Per-point values to color the markers by (e.g. absolute error). Uses the flat style colour when None. cmap, norm : optional Colormap and normalization applied to c.

Returns

fig : matplotlib.figure.Figure ax : matplotlib.axes.Axes

ebf.viz.contour_plot_2d(model, X_data, y_data=None, ax=None, *, n_grid=400, mask=True, n_contours=7, n_contourf=31, cmap=DEFAULT_CMAP, alpha=0.9, xlabel=None, ylabel=None, zlabel=None, show_data=True, show_nodes=False, data_color=None, data_cmap=None, data_norm=None, clabel_fmt='$Z=%.2f$')

Filled contour map for a 2-D input EBF model.

Parameters

model : ebf.EBF A fitted EBF model with 2-D input. X_data : array-like, shape (n_points, 2) Training input points (used for grid bounds and optional mask). y_data : array-like, shape (n_points,), optional Training output values — only needed when mask is True (for convex-hull masking via scipy griddata). ax : matplotlib.axes.Axes, optional Axes to draw on. A new figure is created when None. n_grid : int, optional Grid resolution per axis. Default 400. mask : bool, optional Mask predictions outside the convex hull of training data. Requires y_data. Default True. n_contours : int, optional Number of labelled contour lines. Default 7. n_contourf : int, optional Number of filled contour levels. Default 31. cmap : str, optional Matplotlib colormap. Default 'Blues_r'. Colormaps from cmasher ('cmr.*') are registered and may also be passed. alpha : float, optional Fill opacity. Default 0.9. xlabel, ylabel, zlabel : str, optional Axis / colorbar labels. show_data : bool, optional Overlay training data points. Default True. show_nodes : bool, optional Overlay EBF node positions. Default False. data_color : array-like, shape (n_points,), optional Per-point values to color the data overlay by (e.g. absolute error). Uses the flat white marker face when None. data_cmap, data_norm : optional Colormap and normalization applied to data_color. No colorbar is drawn for it here — the caller owns that (see :func:summary_plot_3d), since the axes already carry the surface colorbar. clabel_fmt : str or None, optional Format string for contour labels. None disables labels. Default '$Z=%.2f$'.

Returns

fig : matplotlib.figure.Figure ax : matplotlib.axes.Axes

ebf.viz.summary_plot_3d(model, X_data, y_data, *, figsize=(12, 8), loss_threshold=None, xlabel=None, ylabel=None, zlabel=None, error_color=True, error_cmap=ERROR_CMAP, **contour_kwargs)

One-figure fit summary for 3-D data (two inputs, one output).

The fitted surface (:func:contour_plot_2d) is the dominant element, filling the full height of the figure on the left; the data-vs-prediction plot (:func:correlation_plot), the residual-vs-predicted plot (:func:residual_plot), and the training loss curve (:func:convergence_plot) are stacked in a narrower column on the right.

By default every data point is shaded by its absolute error on one shared red scale, so the same shade means the same error on all three data panels and a bad point can be traced from the residual plot back to where it sits on the map (error_color=False restores flat markers).

Parameters

model : ebf.EBF A fitted EBF model with 2-D input and a training history. X_data : array-like, shape (n_points, 2) Training input points. y_data : array-like, shape (n_points,) Training output values. figsize : tuple, optional Figure size in inches. Default (12, 8). loss_threshold : float, optional Early-stopping threshold reference line for the convergence panel (pass the same value given to fit()). xlabel, ylabel, zlabel : str, optional Axis / colorbar labels for the contour panel. error_color : bool, optional Shade every data point by its absolute error — same values, same colormap and same scale on all three data panels, with a single shared colorbar down the right-hand edge. Default True; pass False for flat-filled markers. error_cmap : str, optional Colormap for the error_color shading. Default 'Reds'. **contour_kwargs Extra keyword arguments forwarded to :func:contour_plot_2d (e.g. n_grid, mask, cmap, show_nodes).

Returns

fig : matplotlib.figure.Figure axes : ndarray of matplotlib.axes.Axes, shape (4,) (contour, correlation, residual, convergence) axes.

ebf.viz.eval_grid(model, bounds, n_points=50)

Create an n-dimensional rectilinear grid and predict on it.

Parameters

model : ebf.EBF A fitted EBF model. bounds : list of (min, max) Per-dimension (min, max) bounds. n_points : int or list of int, optional Grid resolution. A single int uses the same resolution for every dimension; a list specifies resolution per dimension. Default 50.

Returns

result : dict "coords"ndarray (n_total, n_dims) flat grid points. "predictions"ndarray (n_total,) model output. "grid_shape"tuple of ints, shape for reshaping. "axes"list of 1-D arrays (tick values per dim).

ebf.viz.export_grid(filepath, grid_result, dim_names=None)

Save evaluation-grid results to CSV or NPZ.

The format is chosen by file extension:

  • .csv — flat table with one column per input dimension plus a prediction column. Universal format readable by Excel, MATLAB, C++, etc.
  • .npz — NumPy archive containing coords, predictions, grid_shape, and per-dimension axis arrays axis_0, …

Parameters

filepath : str or pathlib.Path Output file path. Extension determines format. grid_result : dict Output of :func:eval_grid. dim_names : list of str, optional Column names for each input dimension. Defaults to ["dim_0", "dim_1", …].

Basis Function Registry

ebf.basis_functions

Basis function registry for EBF.

BASIS_FUNCTIONS is a dict mapping basis function names to (callable, n_params) tuples.

callable signature (r2, a1, [a2, [a3,]] eps) -> tf.Tensor of shape (n_points,)

Parameters consumed by every callable:

r2 : squared non-Euclidean distance, shape (n_points, n_nodes) a1 : per-node weight tensor, shape (n_nodes,) a2 : per-node weight tensor, shape (n_nodes,) — only for n_params >= 2 a3 : per-node weight tensor, shape (n_nodes,) — only for n_params == 3 eps : small float for numerical stability (user-configurable, default 1e-8)

All current functions use n_params=1. The registry tuple format and the n_params branching in EBFModel are retained to support future multi-parameter basis functions without structural changes.

DEFAULT_BASIS is 'multiquadric' (see ADR-007).

BASIS_FUNCTIONS = {'linear': (lambda r2, a1, eps: tf.reduce_sum(a1 * r2 ** 0.5, axis=1), 1), 'quadratic': (lambda r2, a1, eps: tf.reduce_sum(a1 * r2, axis=1), 1), 'thin_plate': (lambda r2, a1, eps: tf.reduce_sum(tf.math.xlogy(r2, r2) * a1, axis=1), 1), 'multiquadric': (lambda r2, a1, eps: tf.reduce_sum(a1 * ((r2 + 1) ** 0.5 - 1), axis=1), 1), 'inv_multiquadric': (lambda r2, a1, eps: tf.reduce_sum(a1 / (r2 + 1) ** 0.5, axis=1), 1), 'inv_quadratic': (lambda r2, a1, eps: tf.reduce_sum(a1 / (1 + r2), axis=1), 1), 'gaussian': (lambda r2, a1, eps: tf.reduce_sum(a1 * tf.math.exp(-r2), axis=1), 1), 'matern32': (lambda r2, a1, eps: tf.reduce_sum(a1 * (1 + 3 ** 0.5 * r2 ** 0.5) * tf.math.exp(-3 ** 0.5 * r2 ** 0.5), axis=1), 1), 'matern52': (lambda r2, a1, eps: tf.reduce_sum(a1 * (1 + 5 ** 0.5 * r2 ** 0.5 + 5 / 3 * r2) * tf.math.exp(-5 ** 0.5 * r2 ** 0.5), axis=1), 1), 'cosh': (lambda r2, a1, eps: tf.reduce_sum(a1 * tf.math.cosh((r2 + eps) ** 0.5), axis=1), 1), 'cubic': (lambda r2, a1, eps: tf.reduce_sum(a1 * r2 ** 1.5, axis=1), 1), 'inv_cosh': (lambda r2, a1, eps: tf.reduce_sum(a1 / tf.math.cosh((r2 + eps) ** 0.5), axis=1), 1)} module-attribute

DEFAULT_BASIS = 'multiquadric' module-attribute