Decomposition Laplacian Eigenmap#

laplacian_eigenmap #

CLASS DESCRIPTION
LaplacianEigenmap

Laplacian eigenmaps for nonlinear dimensionality reduction.

FUNCTION DESCRIPTION
laplacian_eigenmap

Compute Laplacian eigenmap embedding.

Classes#

LaplacianEigenmap(*, kernel_fn: Kernel | str = 'gaussian', kernel_kwargs: dict | None = None, distance_fn: PairwiseDistance | str = 'euclidean', distance_kwargs: dict | None = None, score_fn: Callable | None = None, out_features: int = 0, symmetric_eigendecomposition: bool = True) #

Bases: Decomposition

Laplacian eigenmaps for nonlinear dimensionality reduction.

Laplacian eigenmaps use graph Laplacian eigendecomposition to find a low-dimensional embedding that preserves local neighborhood structure [@belkin2001laplacian,belkin2003laplacian].

The method constructs a graph Laplacian from pairwise similarities and uses the smallest non-trivial eigenvectors as embedding coordinates.

This implementation uses a modular architecture that separates pairwise distance computation from kernel computation. The kernel must have a normalization configured to construct the appropriate Laplacian type.

PARAMETER DESCRIPTION
kernel_fn

Kernel function for similarity computation. Can be a Kernel instance, string name of a kernel, or None. Use kernel's normalization parameter to control normalization.

TYPE: Kernel | str | None, optional, by default None DEFAULT: 'gaussian'

kernel_kwargs

Additional keyword arguments to pass to the kernel function if kernel_fn is specified as a string.

TYPE: dict | None, optional, by default None DEFAULT: None

distance_fn

Pairwise distance function. Can be a PairwiseDistance instance, string name of a distance function, or None.

TYPE: PairwiseDistance | str | None, optional, by default None DEFAULT: 'euclidean'

distance_kwargs

Additional keyword arguments to pass to the distance function if distance_fn is specified as a string.

TYPE: dict | None, optional, by default None DEFAULT: None

score_fn

Scoring function to evaluate the model. Must be callable if provided. If None, score will raise an error.

TYPE: Callable | None, optional, by default None DEFAULT: None

out_features

Number of eigenvectors to compute. If 0, computes all eigenvectors. Must be non-negative.

TYPE: int, optional, by default 0 DEFAULT: 0

symmetric_eigendecomposition

Whether to perform symmetric eigendecomposition.

TYPE: bool, optional, by default False DEFAULT: True

ATTRIBUTE DESCRIPTION
eigenvalues

Eigenvalues from kernel matrix decomposition of shape (out_features, ).

TYPE: Tensor

eigenvectors

Eigenvectors from kernel matrix decomposition of shape (n_samples, out_features).

TYPE: Tensor

diffusion_coordinates

Diffusion coordinates extracted from the eigenvectors (n_samples, out_features) or (n_samples, out_features - 1).

TYPE: Tensor

kernel

Computed kernel matrix of shape (n_samples, n_samples).

TYPE: Tensor

explained_variance

Explained variance for each component.

TYPE: Tensor

cumulative_explained_variance

Cumulative explained variance for components.

TYPE: Tensor

METHOD DESCRIPTION
score

Compute score using the provided scoring function.

fit

Fit the Laplacian eigenmap to the provided data.

predict

Return extrapolation of the fitted Laplacian embedding coordinates

Source code in spectre/decomposition/laplacian_eigenmap.py
def __init__(
    self,
    *,
    kernel_fn: Kernel | str = "gaussian",
    kernel_kwargs: dict | None = None,
    distance_fn: PairwiseDistance | str = "euclidean",
    distance_kwargs: dict | None = None,
    score_fn: Callable | None = None,
    out_features: int = 0,
    symmetric_eigendecomposition: bool = True,
) -> None:
    super().__init__(
        kernel_fn=kernel_fn,
        kernel_kwargs=kernel_kwargs,
        distance_fn=distance_fn,
        distance_kwargs=distance_kwargs,
        score_fn=score_fn,
    )
    if not isinstance(out_features, int):
        raise TypeError(
            f"Expected `out_features` to be int, got {type(out_features)}"
        )
    check_in_interval(out_features, "[0, inf)")
    self.out_features = out_features

    if not isinstance(symmetric_eigendecomposition, bool):
        raise ValueError("symmetric_eigendecomposition must be a boolean.")
    self.symmetric_eigendecomposition = symmetric_eigendecomposition

    # Internal state.
    self._eigenvalues = None
    self._eigenvectors = None
    self._kernel = None
Attributes#
explained_variance: torch.Tensor property #

Explained variance for each diffusion component.

cumulative_explained_variance: torch.Tensor property #

Cumulative explained variance for embedding dimensions.

eigenvalues: torch.Tensor property #

Eigenvalues of the Laplacian matrix.

eigenvectors: torch.Tensor property #

Eigenvectors of the Laplacian matrix.

kernel: torch.Tensor property #

Computed Laplacian matrix.

Functions#
score(X: torch.Tensor, weights: torch.Tensor | None = None, target: torch.Tensor | None = None, **kwargs) -> float | torch.Tensor #

Compute score using the provided scoring function.

PARAMETER DESCRIPTION
X

Input data of shape (n_samples, n_features).

TYPE: Tensor

weights

Sample weights of shape (n_samples,).

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

target

Target values for scoring.

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

**kwargs

Additional keyword arguments passed to the scoring function.

DEFAULT: {}

RETURNS DESCRIPTION
float | Tensor

Score computed by the scoring function.

Source code in spectre/decomposition/laplacian_eigenmap.py
def score(
    self,
    X: torch.Tensor,
    weights: torch.Tensor | None = None,
    target: torch.Tensor | None = None,
    **kwargs,
) -> float | torch.Tensor:
    """
    Compute score using the provided scoring function.

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

    weights : torch.Tensor | None, optional, by default None
        Sample weights of shape (n_samples,).

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

    **kwargs
        Additional keyword arguments passed to the scoring function.

    Returns
    -------
    float | torch.Tensor
        Score computed by the scoring function.
    """
    if self.score_fn is None:
        raise TypeError("To run `score`, set a `scoring_fn`.")

    self.fit(X, weights=weights)

    return self.score_fn(X, weights=weights, target=target, **kwargs)
fit(X: torch.Tensor, weights: torch.Tensor | None = None, target: torch.Tensor | None = None) -> LaplacianEigenmap #

Fit the Laplacian eigenmap to the provided data.

PARAMETER DESCRIPTION
X

Training data of shape (n_samples, n_features).

TYPE: Tensor

weights

Sample weights of shape (n_samples,).

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

target

Not used in Laplacian eigenmaps (unsupervised method).

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

RETURNS DESCRIPTION
LaplacianEigenmap

Returns self for method chaining.

Source code in spectre/decomposition/laplacian_eigenmap.py
def fit(
    self,
    X: torch.Tensor,
    weights: torch.Tensor | None = None,
    target: torch.Tensor | None = None,
) -> "LaplacianEigenmap":
    """
    Fit the Laplacian eigenmap to the provided data.

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

    weights : torch.Tensor | None, optional, by default None
        Sample weights of shape (n_samples,).

    target : torch.Tensor | None, optional, by default None
        Not used in Laplacian eigenmaps (unsupervised method).

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

    self.in_features = X.shape[1]

    if self.out_features == 0:
        self.out_features = min(X.shape[0], X.shape[1])

    # Store training data for out-of-sample extension.
    self._X_fit = X.clone()
    self._weights_fit = weights.clone() if weights is not None else None

    result = _laplacian_eigenmap_impl(
        X=X,
        weights=weights,
        kernel_fn=self.kernel_fn,
        distance_fn=self.distance_fn,
        out_features=0,
        symmetric_eigendecomposition=self.symmetric_eigendecomposition,
    )

    self.is_fitted = True

    self._eigenvalues = result.eigenvalues
    self._eigenvectors = result.eigenvectors
    self._kernel = result.kernel

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

Return extrapolation of the fitted Laplacian embedding coordinates using Nystrom extension.

PARAMETER DESCRIPTION
X

Input data of shape (n_samples, n_features).

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Embedding coordinates of shape (n_samples, out_features).

Source code in spectre/decomposition/laplacian_eigenmap.py
def predict(self, X: torch.Tensor) -> torch.Tensor:
    """
    Return extrapolation of the fitted Laplacian embedding coordinates
    using Nystrom extension.

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

    Returns
    -------
    torch.Tensor
        Embedding coordinates of shape (n_samples, out_features).
    """
    self.check_fitted()

    if X.shape == self._X_fit.shape and torch.allclose(X, self._X_fit):
        return self._eigenvectors[:, : self.out_features]

    return nystrom_extension(
        X=X,
        X_train=self._X_fit,
        eigenvectors=self._eigenvectors,
        eigenvalues=self._eigenvalues,
        kernel_fn=self.kernel_fn,
        distance_fn=self.distance_fn,
        out_features=self.out_features,
        scale_by_eigenvalues=False,
    )

Functions#

laplacian_eigenmap(X: torch.Tensor, weights: torch.Tensor | None = None, *, kernel_fn: Kernel, distance_fn: PairwiseDistance, out_features: int = 0, symmetric_eigendecomposition: bool = True) -> DecompositionResult #

Compute Laplacian eigenmap embedding.

See [@belkin2001laplacian,belkin2003laplacian].

This function provides a modular approach to Laplacian eigenmaps by separating pairwise distance computation from kernel computation. The kernel must have a normalization configured to construct the appropriate Laplacian type.

PARAMETER DESCRIPTION
Parameters

X

Input data of shape (n_samples, out_features).

TYPE: Tensor

weights

Sample weights of shape (n_samples,). If None, weights are assigned ones.

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

kernel_fn

Kernel function for similarity computation. Must be a Kernel instance. Use kernel's normalization parameter to control normalization.

TYPE: Kernel

distance_fn

Pairwise distance function. Must be a PairwiseDistance instance.

TYPE: PairwiseDistance

out_features

Number of eigenvectors to compute. If 0, computes all eigenvectors. Must be non-negative.

TYPE: int, optional, by default 0 DEFAULT: 0

symmetric_eigendecomposition

Whether to compute symmetric eigendecomposition.

TYPE: bool, optional, by default True DEFAULT: True

RETURNS DESCRIPTION
DecompositionResult

A tuple containing:

  • eigenvalues : Eigenvalues of shape (out_features,)
  • eigenvectors : Eigenvectors of shape (n_samples, out_features)
  • kernel : Kernel matrix of shape (n_samples, n_samples)
Source code in spectre/decomposition/laplacian_eigenmap.py
def laplacian_eigenmap(
    X: torch.Tensor,
    weights: torch.Tensor | None = None,
    *,
    kernel_fn: Kernel,
    distance_fn: PairwiseDistance,
    out_features: int = 0,
    symmetric_eigendecomposition: bool = True,
) -> DecompositionResult:
    """
    Compute Laplacian eigenmap embedding.

    See [@belkin2001laplacian,belkin2003laplacian].

    This function provides a modular approach to Laplacian eigenmaps by separating
    pairwise distance computation from kernel computation. The kernel must have
    a normalization configured to construct the appropriate Laplacian type.

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

    weights : torch.Tensor | None, optional, by default None
        Sample weights of shape (n_samples,). If None, weights are assigned ones.

    kernel_fn : Kernel
        Kernel function for similarity computation. Must be a Kernel instance.
        Use kernel's `normalization` parameter to control normalization.

    distance_fn : PairwiseDistance
        Pairwise distance function. Must be a PairwiseDistance instance.

    out_features : int, optional, by default 0
        Number of eigenvectors to compute. If 0, computes all eigenvectors.
        Must be non-negative.

    symmetric_eigendecomposition : bool, optional, by default True
        Whether to compute symmetric eigendecomposition.

    Returns
    -------
    DecompositionResult
        A tuple containing:

        - eigenvalues : Eigenvalues of shape (out_features,)
        - eigenvectors : Eigenvectors of shape (n_samples, out_features)
        - kernel : Kernel matrix of shape (n_samples, n_samples)
    """
    check_2d(X)

    if not isinstance(kernel_fn, Kernel):
        raise TypeError(
            f"kernel_fn must be Kernel instance, got {type(kernel_fn).__name__}"
        )

    if not isinstance(distance_fn, PairwiseDistance):
        raise TypeError(
            f"distance_fn must be PairwiseDistance instance, "
            f"got {type(distance_fn).__name__}"
        )

    if not isinstance(out_features, int):
        raise TypeError(f"Expected `out_features` to be int, got {type(out_features)}")
    check_in_interval(out_features, "[0, inf)")

    if out_features == 0:
        out_features = min(X.shape[0], X.shape[1])

    if not isinstance(symmetric_eigendecomposition, bool):
        raise ValueError("symmetric_eigendecomposition must be a boolean.")

    return _laplacian_eigenmap_impl(
        X=X,
        weights=weights,
        kernel_fn=kernel_fn,
        distance_fn=distance_fn,
        out_features=out_features,
        symmetric_eigendecomposition=symmetric_eigendecomposition,
    )