Ensemble Bootstrap#

bootstrap #

CLASS DESCRIPTION
BootstrapSpectral

Bootstrap reduction for spectral methods.

Attributes#

Classes#

BootstrapSpectral(estimator: ModelType, n_estimators: int = 10, sample_fraction: float = 1.0, reduce: str = 'mean', fit_manager: FitManager | None = None) #

Bases: Ensemble

Bootstrap reduction for spectral methods.

Fits multiple spectral estimators on bootstrap samples of the data, providing uncertainty quantification. Useful for assessing reliability of spectral features and identifying stable components.

PARAMETER DESCRIPTION
estimator

Base spectral estimator to bootstrap.

TYPE: ModelType

n_estimators

Number of bootstrap samples/estimators to clone.

TYPE: int, by default 10 DEFAULT: 10

sample_fraction

Fraction of data to sample for each bootstrap (0, 1]. Value of 1.0 means sample same size as original data (with replacement).

TYPE: float, by default 1.0 DEFAULT: 1.0

reduce

How to aggregate bootstrap predictions:

  • "mean": Average embeddings
  • "median": Element-wise median

TYPE: str, by default "mean" DEFAULT: 'mean'

fit_manager

Manager for unified training of both Estimator and Parametric models. Required for using Parametric (PyTorch Lightning) models in bootstrap ensemble. See FitManager for configuration options.

TYPE: FitManager | None DEFAULT: None

ATTRIBUTE DESCRIPTION
estimators

Dictionary of fitted bootstrap estimators.

TYPE: dict[str, ModelType]

Examples:

Bootstrap ensemble for diffusion map:

>>> from spectre.decomposition import DiffusionMap
>>> from spectre.kernel import GaussianKernel
>>> from spectre.pairwise_distance import PairwiseDistanceEuclidean
>>> from spectre.ensemble import BootstrapSpectral
>>>
>>> base_dm = DiffusionMap(
...     kernel_fn=GaussianKernel(bw_method="median"),
...     distance_fn=PairwiseDistanceEuclidean(),
...     out_features=5,
... )
>>>
>>> bootstrap = BootstrapSpectral(
...     estimator=base_dm,
...     n_estimators=50,
...     sample_fraction=1.0,
... )

Analyze uncertainty in embeddings:

>>> X_emb, X_lower, X_upper = bootstrap.predict_with_uncertainty(X)
>>> # Identify samples with high uncertainty (wide confidence intervals)
>>> uncertainty = X_upper - X_lower
>>> uncertain_samples = uncertainty.mean(dim=1) > uncertainty.mean() * 2
>>> print(f"Uncertain samples: {uncertain_samples.sum().item()}")
METHOD DESCRIPTION
fit

Fit bootstrap estimators on bootstrap samples.

predict

Reduce predictions from bootstrap estimators.

predict_with_uncertainty

Return predictions with uncertainty estimates.

score

Average score across bootstrap estimators.

Source code in spectre/ensemble/bootstrap.py
def __init__(
    self,
    estimator: ModelType,
    n_estimators: int = 10,
    sample_fraction: float = 1.0,
    reduce: str = "mean",
    fit_manager: FitManager | None = None,
):
    # Validate base estimator
    if not isinstance(estimator, ModelType):
        raise TypeError(
            f"Base `estimator` must be Estimator or Parametric, "
            f"got {type(estimator).__name__}."
        )
    self.base_estimator = estimator

    # Create list of clones
    estimators = [self.clone_estimator(estimator) for _ in range(n_estimators)]
    super().__init__(estimators, fit_manager=fit_manager)

    if not isinstance(n_estimators, int):
        raise TypeError(
            f"Number of estimators `n_estimators` must be an integer, "
            f"got {type(n_estimators)}."
        )
    check_in_interval(n_estimators, "[1, inf)")
    self.n_estimators = n_estimators

    if not isinstance(sample_fraction, (int, float)):
        raise TypeError(
            f"`sample_fraction` must be a number, got {type(sample_fraction).__name__}."
        )
    check_in_interval(sample_fraction, "(0, 1]")
    self.sample_fraction = float(sample_fraction)

    allowed_reduce = ["mean", "median"]
    if reduce not in allowed_reduce:
        raise ValueError(f"Unknown reduce '{reduce}'. Options: {allowed_reduce}.")
    self.reduce = reduce
Functions#
fit(X: torch.Tensor, weights: torch.Tensor | None = None, target: torch.Tensor | None = None) -> BootstrapSpectral #

Fit bootstrap estimators on bootstrap samples.

PARAMETER DESCRIPTION
X

Training data of shape (n_samples, in_features).

TYPE: Tensor

weights

Sample weights.

TYPE: torch.Tensor | None, optional, by default None DEFAULT: None

target

Target values for supervised methods.

TYPE: torch.Tensor | None, optional, by default None DEFAULT: None

RETURNS DESCRIPTION
BootstrapSpectral

Returns self for method chaining.

Source code in spectre/ensemble/bootstrap.py
def fit(
    self,
    X: torch.Tensor,
    weights: torch.Tensor | None = None,
    target: torch.Tensor | None = None,
) -> "BootstrapSpectral":
    """
    Fit bootstrap estimators on bootstrap samples.

    Parameters
    ----------
    X : torch.Tensor
        Training data of shape (n_samples, in_features).

    weights : torch.Tensor | None, optional, by default None
        Sample weights.

    target : torch.Tensor | None, optional, by default None
        Target values for supervised methods.

    Returns
    -------
    BootstrapSpectral
        Returns self for method chaining.
    """
    check_2d(X)

    self.in_features = X.shape[1]
    n_samples = X.shape[0]

    for name, estimator in self._estimators.items():
        # Generate bootstrap sample
        indices = self._generate_bootstrap_indices(n_samples)

        # Sample data
        X_bootstrap = X[indices]
        weights_bootstrap = weights[indices] if weights is not None else None
        target_bootstrap = target[indices] if target is not None else None

        # Fit estimator using FitManager if available
        self._fit_estimator(
            estimator,
            X_bootstrap,
            weights=weights_bootstrap,
            target=target_bootstrap,
            estimator_name=name,
        )

    # Set output features from first estimator
    dummy_pred = list(self._estimators.values())[0].predict(X[:1])
    self.out_features = dummy_pred.shape[1]

    self.is_fitted = True

    return self
predict(X: torch.Tensor) -> torch.Tensor #

Reduce predictions from bootstrap estimators.

PARAMETER DESCRIPTION
X

Input data of shape (n_samples, in_features).

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Reduced prediction of shape (n_samples, out_features).

Source code in spectre/ensemble/bootstrap.py
def predict(self, X: torch.Tensor) -> torch.Tensor:
    """
    Reduce predictions from bootstrap estimators.

    Parameters
    ----------
    X : torch.Tensor
        Input data of shape (n_samples, in_features).

    Returns
    -------
    torch.Tensor
        Reduced prediction of shape (n_samples, out_features).
    """
    self.check_fitted()

    check_2d(X)

    if X.shape[1] != self.in_features:
        raise ValueError(f"Expected {self.in_features} features, got {X.shape[1]}.")

    # Get predictions from all estimators
    predictions = self.predict_ensemble(X)

    # Use base class reduce
    return self.reduce_predictions(predictions, reduce=self.reduce)
predict_with_uncertainty(X: torch.Tensor, confidence_level: float = 0.95) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor] #

Return predictions with uncertainty estimates.

Computes mean prediction and confidence intervals across bootstrap estimators to quantify uncertainty.

PARAMETER DESCRIPTION
X

Input data of shape (n_samples, in_features).

TYPE: Tensor

confidence_level

Confidence level for uncertainty intervals (e.g., 0.95 for 95% CI).

TYPE: float, by default 0.95 DEFAULT: 0.95

RETURNS DESCRIPTION
tuple of torch.Tensor

A tuple containing:

  • Mean prediction of shape (n_samples, out_features)
  • Lower confidence bound of shape (n_samples, out_features)
  • Upper confidence bound of shape (n_samples, out_features)
Source code in spectre/ensemble/bootstrap.py
def predict_with_uncertainty(
    self,
    X: torch.Tensor,
    confidence_level: float = 0.95,
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
    """
    Return predictions with uncertainty estimates.

    Computes mean prediction and confidence intervals across bootstrap
    estimators to quantify uncertainty.

    Parameters
    ----------
    X : torch.Tensor
        Input data of shape (n_samples, in_features).

    confidence_level : float, by default 0.95
        Confidence level for uncertainty intervals (e.g., 0.95 for 95% CI).

    Returns
    -------
    tuple of torch.Tensor
        A tuple containing:

        - Mean prediction of shape (n_samples, out_features)
        - Lower confidence bound of shape (n_samples, out_features)
        - Upper confidence bound of shape (n_samples, out_features)
    """
    self.check_fitted()

    check_2d(X)
    check_in_interval(confidence_level, "(0, 1)")

    if X.shape[1] != self.in_features:
        raise ValueError(f"Expected {self.in_features} features, got {X.shape[1]}.")

    # Get predictions from all estimators
    predictions = list(self.predict_ensemble(X).values())

    # Stack predictions: (n_estimators, n_samples, out_features)
    stacked = torch.stack(predictions, dim=0)

    # Compute mean prediction
    mean_pred = stacked.mean(dim=0)

    # Calculate confidence intervals using percentiles
    alpha = 1 - confidence_level
    lower_percentile = alpha / 2
    upper_percentile = 1 - lower_percentile

    # Compute percentiles along the estimator dimension (dim=0)
    lower_bound = torch.quantile(stacked, lower_percentile, dim=0)
    upper_bound = torch.quantile(stacked, upper_percentile, dim=0)

    return mean_pred, lower_bound, upper_bound
score(X: torch.Tensor, weights: torch.Tensor | None = None, target: torch.Tensor | None = None) -> float #

Average score across bootstrap estimators.

PARAMETER DESCRIPTION
X

Input data.

TYPE: Tensor

weights

Sample weights.

TYPE: torch.Tensor | None, optional, by default None DEFAULT: None

target

Target values.

TYPE: torch.Tensor | None, optional, by default None DEFAULT: None

RETURNS DESCRIPTION
float

Mean score across estimators.

Source code in spectre/ensemble/bootstrap.py
def score(
    self,
    X: torch.Tensor,
    weights: torch.Tensor | None = None,
    target: torch.Tensor | None = None,
) -> float:
    """
    Average score across bootstrap estimators.

    Parameters
    ----------
    X : torch.Tensor
        Input data.

    weights : torch.Tensor | None, optional, by default None
        Sample weights.

    target : torch.Tensor | None, optional, by default None
        Target values.

    Returns
    -------
    float
        Mean score across estimators.
    """
    return self.reduce_scores(
        X,
        weights=weights,
        target=target,
        reduce="mean",
    )

Functions#