Transform Normalize#

normalize #

CLASS DESCRIPTION
L2Normalizer

L2 normalization transformer.

StatefulL2Normalizer

Stateful L2 normalization with invertibility via cached norms.

MinMaxNormalizer

Min-max normalization transformer with pre-computed statistics.

StandardizationTransformer

Standardization (z-score normalization) with pre-computed statistics.

Classes#

L2Normalizer(dim: int = 1, eps: float = 1e-12) #

Bases: Transformer

L2 normalization transformer.

Normalizes each sample to have unit L2 norm (Euclidean norm). Commonly used for feature normalization in machine learning pipelines.

PARAMETER DESCRIPTION
dim

Dimension along which to compute the L2 norm. Default is 1 (normalize across features for batch of samples).

TYPE: int, by default 1 DEFAULT: 1

eps

Small constant added to denominator for numerical stability to avoid division by zero.

TYPE: float, by default 1e-12 DEFAULT: 1e-12

Examples:

Basic usage with 2D data

>>> import torch
>>> from spectre.transform import L2Normalizer
>>> normalizer = L2Normalizer()
>>> X = torch.randn(100, 10)
>>> X_normalized = normalizer.transform(X)
>>> norms = X_normalized.norm(dim=1)
>>> torch.allclose(norms, torch.ones(100))
True

Use with different dimension

>>> normalizer = L2Normalizer(dim=0)  # Normalize across samples
>>> X = torch.randn(100, 10)
>>> X_normalized = normalizer.transform(X)
>>> norms = X_normalized.norm(dim=0)
>>> torch.allclose(norms, torch.ones(10))
True
METHOD DESCRIPTION
transform

Normalize input data to unit L2 norm.

inverse_transform

Inverse transform is not well-defined for L2 normalization.

Source code in spectre/transform/normalize.py
def __init__(self, dim: int = 1, eps: float = 1e-12) -> None:
    super().__init__()
    self.dim = dim
    self.eps = eps
Functions#
transform(X: torch.Tensor) -> torch.Tensor #

Normalize input data to unit L2 norm.

PARAMETER DESCRIPTION
X

Input data to normalize.

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

L2-normalized data with same shape as input.

Source code in spectre/transform/normalize.py
def transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Normalize input data to unit L2 norm.

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


    Returns
    -------
    torch.Tensor
        L2-normalized data with same shape as input.
    """
    norms = X.norm(dim=self.dim, keepdim=True)
    return X / (norms + self.eps)
inverse_transform(X: torch.Tensor) -> torch.Tensor #

Inverse transform is not well-defined for L2 normalization.

L2 normalization loses magnitude information, making exact inverse transformation impossible.

PARAMETER DESCRIPTION
X

Normalized input data.

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Returns input unchanged.

RAISES DESCRIPTION
NotImplementedError

L2 normalization is not invertible.

Source code in spectre/transform/normalize.py
def inverse_transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Inverse transform is not well-defined for L2 normalization.

    L2 normalization loses magnitude information, making exact inverse
    transformation impossible.

    Parameters
    ----------
    X : torch.Tensor
        Normalized input data.


    Returns
    -------
    torch.Tensor
        Returns input unchanged.


    Raises
    ------
    NotImplementedError
        L2 normalization is not invertible.
    """
    raise NotImplementedError(
        "L2 normalization is not invertible as it loses magnitude information."
    )

StatefulL2Normalizer(dim: int = 1, eps: float = 1e-12) #

Bases: Transformer

Stateful L2 normalization with invertibility via cached norms.

Unlike L2Normalizer, this transformer caches the L2 norms computed during transform(), enabling inverse_transform() to recover the original magnitudes. Useful when you need to normalize data temporarily and later restore the original scale.

Important: This transformer is stateful and not thread-safe. Each transform() call overwrites the cached norms, so concurrent or interleaved transform/inverse operations will produce incorrect results.

PARAMETER DESCRIPTION
dim

Dimension along which to compute the L2 norm. Default is 1 (normalize across features for batch of samples).

TYPE: int, by default 1 DEFAULT: 1

eps

Small constant added to denominator for numerical stability.

TYPE: float, by default 1e-12 DEFAULT: 1e-12

ATTRIBUTE DESCRIPTION
_cached_norms

Cached norms from the last transform call. Used for inversion.

TYPE: Tensor | None

Examples:

Basic usage with norm recovery

>>> import torch
>>> from spectre.transform import StatefulL2Normalizer
>>> normalizer = StatefulL2Normalizer()
>>> X = torch.randn(100, 10)
>>> X_normalized = normalizer.transform(X)
>>> # Verify normalization
>>> norms = X_normalized.norm(dim=1)
>>> torch.allclose(norms, torch.ones(100))
True
>>> # Recover original magnitudes
>>> X_recovered = normalizer.inverse_transform(X_normalized)
>>> torch.allclose(X, X_recovered, atol=1e-6)
True

Sequential transform-inverse workflow

>>> normalizer = StatefulL2Normalizer()
>>> X1 = torch.randn(50, 5)
>>> X1_norm = normalizer.transform(X1)
>>> X1_recovered = normalizer.inverse_transform(X1_norm)
>>> torch.allclose(X1, X1_recovered, atol=1e-6)
True
>>> # New transform overwrites cached norms
>>> X2 = torch.randn(50, 5)
>>> X2_norm = normalizer.transform(X2)
>>> X2_recovered = normalizer.inverse_transform(X2_norm)
>>> torch.allclose(X2, X2_recovered, atol=1e-6)
True
Notes
  • State is stored per instance, making this unsuitable for concurrent use
  • Each transform() call overwrites _cached_norms
  • inverse_transform() requires prior transform() call on same instance
  • For stateless normalization without inversion, use L2Normalizer
METHOD DESCRIPTION
transform

Normalize input data and cache norms for inversion.

inverse_transform

Recover original magnitudes using cached norms.

clear_cache

Clear cached norms to free memory.

Source code in spectre/transform/normalize.py
def __init__(self, dim: int = 1, eps: float = 1e-12) -> None:
    super().__init__()
    self.dim = dim
    self.eps = eps
    self._cached_norms: torch.Tensor | None = None
Functions#
transform(X: torch.Tensor) -> torch.Tensor #

Normalize input data and cache norms for inversion.

PARAMETER DESCRIPTION
X

Input data to normalize.

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

L2-normalized data with same shape as input.

Source code in spectre/transform/normalize.py
def transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Normalize input data and cache norms for inversion.

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


    Returns
    -------
    torch.Tensor
        L2-normalized data with same shape as input.
    """
    self._cached_norms = X.norm(dim=self.dim, keepdim=True)
    return X / (self._cached_norms + self.eps)
inverse_transform(X: torch.Tensor) -> torch.Tensor #

Recover original magnitudes using cached norms.

PARAMETER DESCRIPTION
X

Normalized input data.

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Data with original magnitudes restored.

RAISES DESCRIPTION
RuntimeError

If transform() has not been called before inverse_transform().

Notes

The cached norms must match the shape of X along the normalization dimension. Ensure inverse_transform() is called with the same batch/data that was passed to the most recent transform() call.

Source code in spectre/transform/normalize.py
def inverse_transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Recover original magnitudes using cached norms.

    Parameters
    ----------
    X : torch.Tensor
        Normalized input data.


    Returns
    -------
    torch.Tensor
        Data with original magnitudes restored.


    Raises
    ------
    RuntimeError
        If `transform()` has not been called before `inverse_transform()`.


    Notes
    -----
    The cached norms must match the shape of X along the normalization
    dimension. Ensure `inverse_transform()` is called with the same
    batch/data that was passed to the most recent `transform()` call.
    """
    if self._cached_norms is None:
        raise RuntimeError(
            "Cannot inverse transform: no cached norms available. "
            "Call transform() first."
        )

    return X * self._cached_norms
clear_cache() -> None #

Clear cached norms to free memory.

Useful when you're done with inverse transforms and want to release memory held by cached tensors.

Source code in spectre/transform/normalize.py
def clear_cache(self) -> None:
    """
    Clear cached norms to free memory.

    Useful when you're done with inverse transforms and want to
    release memory held by cached tensors.
    """
    self._cached_norms = None

MinMaxNormalizer(data_min: torch.Tensor, data_max: torch.Tensor, feature_range: tuple[float, float] = (0.0, 1.0), eps: float = 1e-12) #

Bases: Transformer

Min-max normalization transformer with pre-computed statistics.

Scales features to a specified range [min_val, max_val] using pre-computed minimum and maximum values. Unlike sklearn's MinMaxScaler which computes statistics during fitting, this transformer uses fixed statistics provided at initialization.

PARAMETER DESCRIPTION
data_min

Minimum values for each feature, shape (n_features,).

TYPE: Tensor

data_max

Maximum values for each feature, shape (n_features,).

TYPE: Tensor

feature_range

Target range for the transformed data.

TYPE: tuple[float, float], by default (0.0, 1.0) DEFAULT: (0.0, 1.0)

eps

Small constant to avoid division by zero.

TYPE: float, by default 1e-12 DEFAULT: 1e-12

Examples:

Scale data to [0, 1] range

>>> import torch
>>> from spectre.transform import MinMaxNormalizer
>>> data_min = torch.tensor([0.0, -5.0, 10.0])
>>> data_max = torch.tensor([10.0, 5.0, 20.0])
>>> normalizer = MinMaxNormalizer(data_min, data_max)
>>> X = torch.tensor([[5.0, 0.0, 15.0], [10.0, 5.0, 20.0]])
>>> X_normalized = normalizer.transform(X)
>>> X_normalized
tensor([[0.5000, 0.5000, 0.5000],
        [1.0000, 1.0000, 1.0000]])

Scale to custom range

>>> normalizer = MinMaxNormalizer(data_min, data_max, feature_range=(-1.0, 1.0))
>>> X_normalized = normalizer.transform(X)
>>> X_normalized.min(), X_normalized.max()
(tensor(-1.), tensor(1.))
METHOD DESCRIPTION
transform

Scale input data to target range using pre-computed statistics.

inverse_transform

Transform data back to original scale.

Source code in spectre/transform/normalize.py
def __init__(
    self,
    data_min: torch.Tensor,
    data_max: torch.Tensor,
    feature_range: tuple[float, float] = (0.0, 1.0),
    eps: float = 1e-12,
) -> None:
    super().__init__()

    if data_min.shape != data_max.shape:
        raise ValueError(
            f"data_min and data_max must have same shape, got "
            f"{data_min.shape} and {data_max.shape}."
        )

    self.register_buffer("data_min", data_min)
    self.register_buffer("data_max", data_max)
    self.register_buffer("data_range", data_max - data_min)
    self.feature_range = feature_range
    self.eps = eps

    # Pre-compute scaling factors
    min_val, max_val = feature_range
    self.register_buffer("scale", torch.tensor(max_val - min_val))
    self.register_buffer("min_val", torch.tensor(min_val))
Functions#
transform(X: torch.Tensor) -> torch.Tensor #

Scale input data to target range using pre-computed statistics.

PARAMETER DESCRIPTION
X

Input data of shape (n_samples, n_features).

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Scaled data in target range, same shape as input.

Source code in spectre/transform/normalize.py
def transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Scale input data to target range using pre-computed statistics.

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


    Returns
    -------
    torch.Tensor
        Scaled data in target range, same shape as input.
    """
    # X_scaled = (X - data_min) / (data_max - data_min) * scale + min_val
    X_std = (X - self.data_min) / (self.data_range + self.eps)
    return X_std * self.scale + self.min_val
inverse_transform(X: torch.Tensor) -> torch.Tensor #

Transform data back to original scale.

PARAMETER DESCRIPTION
X

Scaled input data of shape (n_samples, n_features).

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Data in original scale, same shape as input.

Source code in spectre/transform/normalize.py
def inverse_transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Transform data back to original scale.

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


    Returns
    -------
    torch.Tensor
        Data in original scale, same shape as input.
    """
    # Reverse: X_original = (X - min_val) / scale * data_range + data_min
    X_std = (X - self.min_val) / self.scale
    return X_std * self.data_range + self.data_min

StandardizationTransformer(mean: torch.Tensor, std: torch.Tensor, eps: float = 1e-12) #

Bases: Transformer

Standardization (z-score normalization) with pre-computed statistics.

Transforms features to have zero mean and unit variance using pre-computed mean and standard deviation. Unlike sklearn's StandardScaler which computes statistics during fitting, this transformer uses fixed statistics provided at initialization.

PARAMETER DESCRIPTION
mean

Mean values for each feature, shape (n_features,).

TYPE: Tensor

std

Standard deviation for each feature, shape (n_features,).

TYPE: Tensor

eps

Small constant added to standard deviation to avoid division by zero.

TYPE: float, by default 1e-12 DEFAULT: 1e-12

Examples:

Standardize data with known statistics

>>> import torch
>>> from spectre.transform import StandardizationTransformer
>>> mean = torch.tensor([0.5, 1.0, 1.5])
>>> std = torch.tensor([0.1, 0.2, 0.3])
>>> standardizer = StandardizationTransformer(mean, std)
>>> X = torch.tensor([[0.5, 1.0, 1.5], [0.6, 1.2, 1.8]])
>>> X_std = standardizer.transform(X)
>>> X_std[0]  # First row (equal to mean) should be zeros
tensor([0., 0., 0.])
>>> X_std[1]  # Second row (one std away) should be ones
tensor([1., 1., 1.])

Inverse transformation

>>> X_reconstructed = standardizer.inverse_transform(X_std)
>>> torch.allclose(X_reconstructed, X)
True
METHOD DESCRIPTION
transform

Standardize input data using pre-computed statistics.

inverse_transform

Transform standardized data back to original scale.

Source code in spectre/transform/normalize.py
def __init__(
    self,
    mean: torch.Tensor,
    std: torch.Tensor,
    eps: float = 1e-12,
) -> None:
    super().__init__()

    if mean.shape != std.shape:
        raise ValueError(
            f"mean and std must have same shape, got {mean.shape} and {std.shape}."
        )

    self.register_buffer("mean", mean)
    self.register_buffer("std", std)
    self.eps = eps
Functions#
transform(X: torch.Tensor) -> torch.Tensor #

Standardize input data using pre-computed statistics.

PARAMETER DESCRIPTION
X

Input data of shape (n_samples, n_features).

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Standardized data with same shape as input.

Source code in spectre/transform/normalize.py
def transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Standardize input data using pre-computed statistics.

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


    Returns
    -------
    torch.Tensor
        Standardized data with same shape as input.
    """
    return (X - self.mean) / (self.std + self.eps)
inverse_transform(X: torch.Tensor) -> torch.Tensor #

Transform standardized data back to original scale.

PARAMETER DESCRIPTION
X

Standardized input data of shape (n_samples, n_features).

TYPE: Tensor

RETURNS DESCRIPTION
Tensor

Data in original scale, same shape as input.

Source code in spectre/transform/normalize.py
def inverse_transform(self, X: torch.Tensor) -> torch.Tensor:
    """
    Transform standardized data back to original scale.

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


    Returns
    -------
    torch.Tensor
        Data in original scale, same shape as input.
    """
    return X * self.std + self.mean