spd_learn.functional.log_cholesky_mean#

spd_learn.functional.log_cholesky_mean(matrices, weights=None)[source]#

Compute the weighted mean in the Log-Cholesky space.

The Log-Cholesky mean is the arithmetic mean of the Log-Cholesky representations, mapped back to the SPD manifold:

\[\bar{X} = \exp_{\text{chol}}\left(\sum_{i=1}^{N} w_i \log_{\text{chol}}(L_i)\right)\]

where \(w_i\) are the weights (summing to 1) and \(X_i = L_i L_i^T\).

Parameters:
  • matrices (torch.Tensor) – SPD matrices of shape (N, …, n, n) where N is the number of matrices to average.

  • weights (torch.Tensor, optional) – Weights of shape (N,) or broadcastable. If None, uniform weights are used. Weights are automatically normalized to sum to 1.

Returns:

Mean SPD matrix of shape (…, n, n).

Return type:

torch.Tensor

Notes

The Log-Cholesky mean has the following properties [Lin, 2019]:

  • It is the unique minimizer of the sum of squared Log-Cholesky distances.

  • It can be computed in closed form (no iterative optimization required).

  • It is computationally more efficient than the Fréchet mean under AIRM.

See also

log_cholesky_distance()

Distance under Log-Cholesky metric.

log_cholesky_geodesic()

Geodesic interpolation under Log-Cholesky metric.

log_euclidean_mean()

Mean under Log-Euclidean metric.

bures_wasserstein_mean()

Mean under Bures-Wasserstein metric.

SPDBatchNormMeanVar

Uses Fréchet mean for batch normalization.

Examples

>>> import torch
>>> # Create 4 SPD matrices of size 3x3
>>> matrices = torch.stack([
...     torch.eye(3),
...     2 * torch.eye(3),
...     3 * torch.eye(3),
...     4 * torch.eye(3)
... ])
>>> mean = log_cholesky_mean(matrices)
>>> print(f"Mean diagonal: {torch.diag(mean)}")
Mean diagonal: tensor([2.2134, 2.2134, 2.2134])