Riemannian Distances¶
The Riemannian distance is a method for comparing RDMs originally proposed by Shahbazi et al. (2021). It is the Riemannian geodesic distance in the space of positive definite matrices. It is a bit more computationally expensive to compute, but performed well as a stable comparison metric.
Main differences to other RDM comparison measures in our toolbox are:
To convert into a similarity measure, we take the negative of the Riemannian distance. As a consequence all results are negative and 0 is an absolute upper bound to RDM similarity or model performance. This is normal for this metric.
Computing the Riemannian distance requires an optimization to adjust a mixture of the noise second moment matrix and the second moment matrix according to the other RDM. This results in a relatively high computational effort.
Conversion to second moment matrices¶
To apply Riemannian distances RDMs, we need to transform the RDMs into second moment matrices. To do so, we need to find a linear and one-to-one transformtion from the dissimilarity into the inner product (positive definite second moment) space. When we calculate the RDM from the pattern matrix, we lose the information of the mean pattern. The second moment matrix calculating from the RDM assuming that the origin is zero, has inherently one zero eigenvalue. Therefore the Riemanninan distances calculating between these second moments are equal to infinity. One alternative is to set the activity pattern of one condition to the origin which results to a \((n_{cond}-1)\times(n_{cond}-1)\) second moment matrix.
For example, say, \(b_1\), \(b_1\), and \(b_3\) are the activity patterns for three condition. The RDM matrix would take the form like this:
Now, for transforming into the inner product space assuming that \(b_1\) is the origin, the resulting second moment will be:
. It is important to note that the new second moment matrix has the same information as the RDM, meaning that there is one linear one-to-one transformation between them. In this low dimensional exmaple the linear transformation between the vectorized RDM and second moment would be:
Fortunately, affine invariance property of Riemannian metric, dictates even if we have used each of remaining conditions (or linear combination of them) as the new origin, the distance would remain the same.
In order to improve the inference, Riemannian distance also benefits from the patterns estimate covariance, \(\Sigma_k\). The resulting measure would be:
where \(\lambda_i\) is the \(i^{th}\) eigenvalue of \(G_{data}^{-1}(\alpha G_{model}+\beta P\Sigma_k P)\)
\(P\): projection matrix on the first condition. \(G_{data}\): second moment coming from the data RDM - procedure explained above. \(G_{model}\): second moment coming from the model RDM we want to test. \(\Sigma_k\): patterns estimate covariance could come from the first level GLM estimate.
Implementation in the toolbox¶
The negative Riemannian distance is available as a normal RDM comparison metric in the toolbox. Useage for a given RDM and a random RDM generated to be somewhat close is illustrated below:
[1]:
import numpy as np
from scipy.spatial.distance import squareform
from rsatoolbox.rdm.compare import compare_neg_riemannian_distance
from rsatoolbox.model import ModelFixed
from rsatoolbox.simulation import make_dataset
from rsatoolbox.rdm import calc_rdm, RDMs
[2]:
# defining the model_rdm
model_rdm = np.array([
[0. , 0.98, 2.18, 2.18, 2.18, 2.18],
[0.98, 0. , 2.18, 2.18, 2.18, 2.18],
[2.18, 2.18, 0. , 0.98, 2.18, 2.18],
[2.18, 2.18, 0.98, 0. , 2.18, 2.18],
[2.18, 2.18, 2.18, 2.18, 0. , 0.98],
[2.18, 2.18, 2.18, 2.18, 0.98, 0. ]])
# vectorize the model and feed make the model_rdm object
model_rdm = squareform(model_rdm)
model_rdm = RDMs(
dissimilarities=model_rdm,
dissimilarity_measure='test',
descriptors={'session': 0, 'subj': 0})
# genrate a dataset from the model_rdm; make_dataset function add noise assuming pattern estimates are uncorrelated (sigma_k=I)
dataset = make_dataset(ModelFixed('model_rdm',model_rdm), theta=None, cond_vec=np.array([0, 1, 2, 3, 4, 5]), n_channel=100)
# the rdm calculated from the noisy dataset
data_rdm = calc_rdm(dataset, method='euclidean')
# the negative riemannian distance between model and data rdms
neg_riem_dist = compare_neg_riemannian_distance(model_rdm, data_rdm, sigma_k=np.eye(6))
print(neg_riem_dist)
[[-0.56616237]]