spd_learn.models.SPNN#

class spd_learn.models.SPNN(n_chans: int = 22, n_outputs: int = 2, bimap_dims: Tuple[int, ...] = (16, 12), metric: str = 'LEM', theta: float = 0.5, drop_prob: float = 0.0)[source]#

Bases: Module

Symmetric Positive Definite Neural Network (SPNN).

Implements the deep Riemannian architecture introduced in RieTrans [Chen et al., 2026]. SPNN transforms covariance representations through a cascade of intrinsic Riemannian linear layers (SPDLinear) interleaved with Riemannian non-linear activation (ReEig), and performs final classification via Riemannian Multinomial Logistic Regression (SPDRMLR):

\[X \xrightarrow{\text{Cov}} C \xrightarrow{\text{TraceNorm}} C_1 \xrightarrow{\text{Shrinkage}} C_2 \xrightarrow{\text{SPDLinear} + \text{ReEig}} \dots \xrightarrow{\text{SPDRMLR}} \hat{y}\]
Parameters:
  • n_chans (int, default=22) – Number of EEG channels (input dimensionality).

  • n_outputs (int, default=2) – Number of output classification classes.

  • bimap_dims (tuple of int, default=(16, 12)) – Intermediate SPD manifold dimensions for the stacked BiMap and SPDLinear layers.

  • metric ({"LEM", "LCM", "AIM", "PEM"}, default="LEM") – Riemannian metric for the SPDLinear and SPDRMLR layers.

  • theta (float, default=0.5) – Power deformation parameter for PEM or RieTrans transformations.

  • drop_prob (float, default=0.0) – Dropout probability. If > 0, applies SPDDropout between intermediate SPD layers.

References

[1]

Ziheng Chen, Yue Song, Yunmei Liu, and Nicu Sebe. Riemannian multinomial logistic regression for symmetric positive definite matrices. In Advances in Neural Information Processing Systems, volume 37. 2024. URL: https://openreview.net/forum?id=V2m8XQ9j3H.

[2]

Ziheng Chen, Rui Wang, and Nicu Sebe. Building transformation layers for riemannian neural networks. In Advances in Neural Information Processing Systems, volume 39. 2026. URL: https://openreview.net/forum?id=GitZH-Chen/RieTrans.

Examples

>>> import torch
>>> from spd_learn.models import SPNN
>>> model = SPNN(n_chans=22, n_outputs=2)
>>> x = torch.randn(4, 22, 1000)
>>> out = model(x)
>>> out.shape
torch.Size([4, 2])
forward(x: Tensor) → Tensor[source]#

Forward pass of SPNN.

Parameters:

x (torch.Tensor) – Input tensor of shape (…, n_chans, n_times) or (…, n_chans, n_chans).

Returns:

Classification logits of shape (…, n_outputs).

Return type:

torch.Tensor