Metrics Manifold#

manifold #

FUNCTION DESCRIPTION
intrinsic_dimension

Estimate intrinsic dimension of data manifold.

Functions#

intrinsic_dimension(X: torch.Tensor, method: str = 'twonn', k_neighbor: int = 50, eps: float = torch.finfo(torch.float32).eps) -> torch.Tensor #

Estimate intrinsic dimension of data manifold.

Intrinsic dimension is the minimum number of parameters needed to describe the data.

PARAMETER DESCRIPTION
X

Data matrix, shape (n_samples, in_features).

TYPE: Tensor

method

Estimation method:

  • "twonn": Two nearest neighbors estimator [1]. Most robust to curvature and density variations. Uses ratio of distances to second or first nearest neighbors. Recommended for high-dimensional data.

  • "mle": Maximum likelihood estimator [2]. Estimates dimension from local neighborhood distances.

TYPE: str, optional, by default "twonn" DEFAULT: 'twonn'

k_neighbor

Number of neighbors for MLE estimation. Ignored for TwoNN.

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

eps

Small constant to avoid numerical issues.

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

RETURNS DESCRIPTION
Tensor

Estimated intrinsic dimension (scalar).

Examples:

Estimate intrinsic dimension of Swiss roll (2D manifold):

>>> from sklearn.datasets import make_swiss_roll
>>> X = torch.from_numpy(make_swiss_roll(n_samples=500, noise=0.0)[0])
>>> intrinsic_dimension(torch.from_numpy(X), method="twonn")
2.05

Compare different estimators:

>>> id_twonn = intrinsic_dimension(X, method="twonn")
>>> id_mle = intrinsic_dimension(X, method="mle", k_neighbor=20)
>>> print(f"TwoNN: {id_twonn:.2f}, MLE: {id_mle:.2f}")
TwoNN: 2.05, MLE: 1.98
Source code in spectre/metrics/manifold.py
def intrinsic_dimension(
    X: torch.Tensor,
    method: str = "twonn",
    k_neighbor: int = 50,
    eps: float = torch.finfo(torch.float32).eps,
) -> torch.Tensor:
    """
    Estimate intrinsic dimension of data manifold.

    Intrinsic dimension is the minimum number of parameters needed to
    describe the data.

    Parameters
    ----------
    X : torch.Tensor
        Data matrix, shape (n_samples, in_features).

    method : str, optional, by default "twonn"
        Estimation method:

        - `"twonn"`: Two nearest neighbors estimator [@facco2017estimating].
          Most robust to curvature and density variations. Uses ratio of
          distances to second or first nearest neighbors. Recommended for
          high-dimensional data.

        - `"mle"`: Maximum likelihood estimator [@levina2004maximum].
          Estimates dimension from local neighborhood distances.

    k_neighbor : int, optional, by default 50
        Number of neighbors for MLE estimation. Ignored for TwoNN.

    eps : float, optional, by default torch.finfo(torch.float32).eps
        Small constant to avoid numerical issues.

    Returns
    -------
    torch.Tensor
        Estimated intrinsic dimension (scalar).

    Examples
    --------
    Estimate intrinsic dimension of Swiss roll (2D manifold):

    >>> from sklearn.datasets import make_swiss_roll
    >>> X = torch.from_numpy(make_swiss_roll(n_samples=500, noise=0.0)[0])
    >>> intrinsic_dimension(torch.from_numpy(X), method="twonn")
    2.05

    Compare different estimators:

    >>> id_twonn = intrinsic_dimension(X, method="twonn")
    >>> id_mle = intrinsic_dimension(X, method="mle", k_neighbor=20)
    >>> print(f"TwoNN: {id_twonn:.2f}, MLE: {id_mle:.2f}")
    TwoNN: 2.05, MLE: 1.98
    """
    check_2d(X)

    if method == "twonn":
        return _intrinsic_dimension_twonn(X, eps=eps)
    elif method == "mle":
        if not isinstance(k_neighbor, int):
            raise TypeError(
                f"Expected `k_neighbor` to be an integer, got {type(k_neighbor).__name__}."
            )
        check_in_interval(k_neighbor, f"[1, {X.shape[0]}]")
        return _intrinsic_dimension_mle(X, k_neighbor=k_neighbor, eps=eps)
    else:
        raise ValueError(f"Unknown method '{method}'. Options: 'twonn', 'mle'.")