Kernel Normalization#

normalization #

CLASS DESCRIPTION
KernelNormalizer

Unified kernel normalization for spectral methods and graph Laplacians.

Classes#

KernelNormalizer(norm_type: NormalizationType = 'markov_symmetric', alpha: float = 0.5, eps: float = torch.finfo(torch.float32).eps) #

Unified kernel normalization for spectral methods and graph Laplacians.

Provides a comprehensive interface for normalizing kernel matrices using various schemes suitable for diffusion maps, spectral clustering, and graph-based methods.

The normalizer is stateful and stores the density vector after each call, which can be accessed for analysis or use in other methods.

PARAMETER DESCRIPTION
norm_type

Type of normalization to apply.

  • "unnormalized": No normalization (returns original kernel)
  • "markov_symmetric": Conjugate symmetric Markov matrix (diffusion maps)
  • "markov_nonsymmetric": Anisotropic row-stochastic Markov matrix
  • "laplacian_symmetric": Symmetric normalized Laplacian \((I - T_{sym})\)
  • "laplacian_nonsymmetric": Nonsymmetric normalized Laplacian \((I - T)\)
  • "laplacian_unnormalized": Unnormalized Laplacian \((D - K)\)

TYPE: NormalizationType, optional, by default "markov_symmetric" DEFAULT: 'markov_symmetric'

alpha

Anisotropy parameter for density correction. Controls the strength of density-based reweighting. Must be in [0, 1]. When alpha=0, no anisotropic correction is applied.

TYPE: float, optional, by default 0.5 DEFAULT: 0.5

eps

Small epsilon added to density for numerical stability.

TYPE: float, optional, by default torch.finfo(torch.float32).eps DEFAULT: eps

ATTRIBUTE DESCRIPTION
q

Density vector computed during the last normalization call. Shape (n_samples,).

TYPE: Tensor | None

Examples:

>>> import torch
>>> from spectre.kernel import GaussianKernel, KernelNormalizer
>>>
>>> # Create data and kernel
>>> X = torch.randn(50, 3)
>>> kernel = GaussianKernel(normalize=False)
>>> K = kernel(X)
>>>
>>> # Apply Markov normalization (diffusion maps style)
>>> normalizer = KernelNormalizer("markov_symmetric")
>>> T_sym = normalizer(K)
>>>
>>> # Compute Laplacian
>>> normalizer = KernelNormalizer("laplacian_symmetric")
>>> L_sym = normalizer(K)  # Returns I - T_sym
Source code in spectre/kernel/normalization.py
def __init__(
    self,
    norm_type: NormalizationType = "markov_symmetric",
    alpha: float = 0.5,
    eps: float = torch.finfo(torch.float32).eps,
):
    valid_types = {
        "unnormalized",
        "markov_symmetric",
        "markov_nonsymmetric",
        "laplacian_symmetric",
        "laplacian_nonsymmetric",
        "laplacian_unnormalized",
    }
    if norm_type not in valid_types:
        raise ValueError(
            f"Normalization type `norm_type` must be one of {valid_types}, got {norm_type}."
        )
    self.norm_type = norm_type

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

    if not isinstance(eps, float):
        raise ValueError(
            f"Regularization constant `eps` must be a float, got {type(eps).__name__}."
        )
    check_in_interval(eps, "[0, inf)")
    self.eps = eps

    # Density vector (set during normalization)
    self.q: torch.Tensor | None = None

Functions#