Manifold Learning Methods
Riemann Geometry
Riemannian Geometry for BCI.
- class brainda.algorithms.manifold.riemann.Alignment(align_method: str = 'euclid', cov_method: str = 'lwf', n_jobs: Optional[int] = None)
Bases:
sklearn.base.BaseEstimator,sklearn.base.TransformerMixinRiemannian/Euclidean Alignment.
- fit(X: numpy.ndarray, y: Optional[numpy.ndarray] = None)
- transform(X)
- class brainda.algorithms.manifold.riemann.FGDA(n_jobs=1)
Bases:
sklearn.base.BaseEstimator,sklearn.base.TransformerMixinFisher Geodesic Discriminat Analysis.
- fit(X, y)
- transform(X)
- class brainda.algorithms.manifold.riemann.FgMDRM(n_jobs: Optional[int] = None)
Bases:
sklearn.base.BaseEstimator,sklearn.base.TransformerMixin,sklearn.base.ClassifierMixin- fit(X: numpy.ndarray, y: numpy.ndarray, sample_weight: Optional[numpy.ndarray] = None)
- predict(X: numpy.ndarray)
- transform(X: numpy.ndarray)
- class brainda.algorithms.manifold.riemann.MDRM(n_jobs: Optional[int] = None)
Bases:
sklearn.base.BaseEstimator,sklearn.base.TransformerMixin,sklearn.base.ClassifierMixin- fit(X: numpy.ndarray, y: numpy.ndarray, sample_weight: Optional[numpy.ndarray] = None)
- predict(X: numpy.ndarray)
- predict_proba(X: numpy.ndarray)
- transform(X: numpy.ndarray)
- class brainda.algorithms.manifold.riemann.RecursiveAlignment(align_method: str = 'euclid', cov_method: str = 'lwf', n_jobs: Optional[int] = None)
Bases:
sklearn.base.BaseEstimator,sklearn.base.TransformerMixinRecursive Riemannian/Euclidean Alignment.
- fit(X, y=None)
- transform(X)
- class brainda.algorithms.manifold.riemann.TSClassifier(clf=LogisticRegression(), n_jobs=None)
Bases:
sklearn.base.BaseEstimator,sklearn.base.ClassifierMixin- fit(X: numpy.ndarray, y: numpy.ndarray)
- predict(X: numpy.ndarray)
- predict_proba(X: numpy.ndarray)
- brainda.algorithms.manifold.riemann.distance_riemann(A: numpy.ndarray, B: numpy.ndarray, n_jobs: Optional[int] = None)
Riemannian distance between two covariance matrices A and B.
- Parameters
A (ndarray) – First positive-definite matrix, shape (n_trials, n_channels, n_channels) or (n_channels, n_channels).
B (ndarray) – Second positive-definite matrix.
- Returns
Riemannian distance between A and B.
- Return type
ndarray | float
Notes
\[d = {\left( \sum_i \log(\lambda_i)^2 \right)}^{-1/2}\]where \(\lambda_i\) are the joint eigenvalues of A and B.
- brainda.algorithms.manifold.riemann.expmap(Si: numpy.ndarray, P: numpy.ndarray, n_jobs: Optional[int] = None)
Exponential map from the tangent space to the positive-definite space.
Exponential map projects \(\mathbf{S}_i \in \mathcal{T}_{\mathbf{P}} \mathcal{M}\) bach to the manifold \(\mathcal{M}\).
- Parameters
Si (ndarray) – Tangent space point (in matrix form).
P (ndarray) – Reference point.
n_jobs (int, optional) – the number of jobs to use.
- Returns
Pi – SPD matrix.
- Return type
ndarray
- brainda.algorithms.manifold.riemann.geodesic(P1: numpy.ndarray, P2: numpy.ndarray, t: float, n_jobs: Optional[int] = None)
Geodesic.
The geodesic curve between any two SPD matrices \(\mathbf{P}_1,\mathbf{P}_2 \in \mathcal{M}\).
- Parameters
P1 (ndarray) – SPD matrix.
P2 (ndarray) – SPD matrix, the same shape of P1.
t (float) – \(0 \leq t \leq 1\).
n_jobs (int, optional) – the number of jobs to use.
- Returns
phi – SPD matrix on the geodesic curve between P1 and P2.
- Return type
ndarray
- brainda.algorithms.manifold.riemann.logmap(Pi: numpy.ndarray, P: numpy.ndarray, n_jobs: Optional[int] = None)
Logarithm map from the positive-definite space to the tangent space.
Logarithm map projects \(\mathbf{P}_i \in \mathcal{M}\) to the tangent space point \(\mathbf{S}_i \in \mathcal{T}_{\mathbf{P}} \mathcal{M}\) at \(\mathbf{P} \in \mathcal{M}\).
- Parameters
Pi (ndarray) – SPD matrix.
P (ndarray) – Reference point.
n_jobs (int, optional) – the number of jobs to use.
- Returns
Si – Tangent space point (in matrix form).
- Return type
ndarray
- brainda.algorithms.manifold.riemann.mdrm_kernel(X: numpy.ndarray, y: numpy.ndarray, sample_weight: Optional[numpy.ndarray] = None, n_jobs: Optional[int] = None)
Minimum Distance to Riemannian Mean.
- Parameters
X (ndarray) – eeg data, shape (n_trials, n_channels, n_samples)
y (ndarray) – labels, shape (n_trials)
sample_weight (Optional[ndarray], optional) – sample weights, by default None
n_jobs (Optional[int], optional) – the number of jobs to use, by default None
- Returns
centroids of each class, shape (n_class, n_channels, n_channels).
- Return type
ndarray
- brainda.algorithms.manifold.riemann.mean_riemann(covmats, tol=1e-11, maxiter=300, init=None, sample_weight=None, n_jobs=None)
Return the mean covariance matrix according to the Riemannian metric.
- Parameters
covmats (ndarray) – Covariance matrices set, shape (n_trials, n_channels, n_channels).
tol (float, optional) – The tolerance to stop the gradient descent (default 1e-8).
maxiter (int, optional) – The maximum number of iteration (default 50).
init (None|ndarray, optional) – A covariance matrix used to initialize the gradient descent (default None), if None the arithmetic mean is used.
sample_weight (None|ndarray, optional) – The weight of each sample (efault None), if None weights are 1 otherwise weights are normalized.
- Returns
C – The Riemannian mean covariance matrix.
- Return type
ndarray
Notes
The procedure is similar to a gradient descent minimizing the sum of riemannian distance to the mean.
\[\mathbf{C} = \arg \min{(\sum_i \delta_R ( \mathbf{C} , \mathbf{C}_i)^2)}\]where :math:delta_R is riemann distance.
- brainda.algorithms.manifold.riemann.tangent_space(Pi: numpy.ndarray, P: numpy.ndarray, n_jobs: Optional[int] = None)
Logarithm map projects SPD matrices to the tangent vectors.
- Parameters
Pi (ndarray) – SPD matrices, shape (n_trials, n_channels, n_channels).
P (ndarray) – Reference point.
- Returns
vSi – Tangent vectors, shape (n_trials, n_channels*(n_channels+1)/2).
- Return type
ndarray
- brainda.algorithms.manifold.riemann.untangent_space(vSi: numpy.ndarray, P: numpy.ndarray, n_jobs: Optional[int] = None)
Logarithm map projects SPD matrices to the tangent vectors.
- Parameters
vSi (ndarray) – Tangent vectors, shape (n_trials, n_channels*(n_channels+1)/2).
P (ndarray) – Reference point.
- Returns
Pi – SPD matrices, shape (n_trials, n_channels, n_channels).
- Return type
ndarray
- brainda.algorithms.manifold.riemann.unvectorize(vSi: numpy.ndarray)
unvectorize tangent space points.
- Parameters
vSi (ndarray) – vectorized version of Si, shape (n_trials, n_channels*(n_channels+1)/2)
- Returns
points in the tangent space, shape (n_trials, n_channels, n_channels)
- Return type
ndarray
- brainda.algorithms.manifold.riemann.vectorize(Si: numpy.ndarray)
vectorize tangent space points.
- Parameters
Si (ndarray) – points in the tangent space, shape (n_trials, n_channels, n_channels)
- Returns
vectorized version of Si, shape (n_trials, n_channels*(n_channels+1)/2)
- Return type
ndarray
Riemann Procrustes Analysis
Riemannian Procrustes Analysis. Modified from https://github.com/plcrodrigues/RPA
- brainda.algorithms.manifold.rpa.get_recenter(X: numpy.ndarray, cov_method: str = 'cov', mean_method: str = 'riemann', n_jobs: Optional[int] = None)
- brainda.algorithms.manifold.rpa.get_rescale(X: numpy.ndarray, cov_method: str = 'cov', n_jobs: Optional[int] = None)
- brainda.algorithms.manifold.rpa.get_rotate(Xs: numpy.ndarray, ys: numpy.ndarray, Xt: numpy.ndarray, yt: numpy.ndarray, cov_method: str = 'cov', metric: str = 'euclid', n_jobs: Optional[int] = None)
- brainda.algorithms.manifold.rpa.recenter(X: numpy.ndarray, iM12: numpy.ndarray)
- brainda.algorithms.manifold.rpa.rescale(X: numpy.ndarray, M: numpy.ndarray, scale: float, cov_method: str = 'cov', n_jobs: Optional[int] = None)
- brainda.algorithms.manifold.rpa.rotate(Xt: numpy.ndarray, Ropt: numpy.ndarray)