def transform(self, X): """Apply transform to covariances Parameters ---------- covs: list of array list of covariance matrices, shape (n_rois, n_rois) Returns ------- list of array, transformed covariance matrices, shape (n_rois * (n_rois+1)/2,) """ covs = [self.cov_estimator_.fit(x).covariance_ for x in X] covs = spd_mfd.my_stack(covs) if self.kind == 'tangent': covs = [spd_mfd.logm(self.whitening_.dot(c).dot(self.whitening_)) for c in covs] elif self.kind == 'precision': covs = [spd_mfd.inv(g) for g in covs] elif self.kind == 'partial correlation': covs = [prec_to_partial(spd_mfd.inv(g)) for g in covs] elif self.kind == 'correlation': covs = [cov_to_corr(g) for g in covs] else: raise ValueError("Unknown connectivity measure.") return np.array([sym_to_vec(c) for c in covs])
def test_my_stack(): """Testing my_stack function""" mats = [] for n in xrange(7): mats.append(np.random.rand(31, 31)) stacked = my_mfd.my_stack(mats) assert_is_instance(stacked, np.ndarray) assert_tuple_equal(stacked.shape, (7, 31, 31)) for n in xrange(7): assert_array_equal(stacked[n], mats[n])
def test_frechet_mean(): # TODO: test suite and split in several tests """Testing frechet_mean function""" n = random.randint(3, 50) shape = random.randint(1, 50) spds = [] for k in xrange(n): eig_min = random.uniform(1e-7, 1.) eig_max = random.uniform(1., 1e7) spds.append(my_mfd.random_spd(shape, eig_min, eig_max)) fre = my_mfd.frechet_mean(spds) # Generic assert_tuple_equal(fre.shape, spds[0].shape) assert_array_almost_equal(fre, fre.T) assert_array_less(0., linalg.eigvals(fre)) # Check error for non spd enteries mat1 = np.ones((shape, shape)) with assert_raises_regexp(ValueError, "at least one matrix is not real " +\ "spd"): my_mfd.frechet_mean([mat1]) # Check warning if gradient norm in the last step is less than tolerance for (tol, max_iter) in [(1e-10, 1), (1e-3, 50)]: with warnings.catch_warnings(record=True) as w: fre = my_mfd.frechet_mean(spds, max_iter=max_iter, tol=tol) grad_norm = my_mfd.grad_frechet_mean(spds, max_iter=max_iter, tol=tol) if grad_norm[-1] > tol: assert_equal(len(w), 2) assert_equal(len(grad_norm), max_iter) # Gradient norm is decreasing assert_array_less(np.diff(grad_norm), 0.) decimal = 5 tol = 10 ** (-2 * decimal) fre = my_mfd.frechet_mean(spds, tol=tol) # Adaptative version requires less iterations than non adaptaive grad_norm = my_mfd.grad_frechet_mean(spds, tol=tol) grad_norm_fast = my_mfd.grad_frechet_mean(spds, tol=tol, adaptative=True) assert(len(grad_norm_fast) == len(grad_norm)) # Invariance under reordering spds.reverse() spds.insert(0, spds[2]) spds.pop(3) fre_new = my_mfd.frechet_mean(spds, tol=tol) assert_array_almost_equal(fre_new, fre) # Invariance under congruant transformation c = my_mfd.random_non_singular(shape) spds_cong = [c.dot(spd).dot(c.T) for spd in spds] fre_new = my_mfd.frechet_mean(spds_cong, tol=tol) assert_array_almost_equal(fre_new, c.dot(fre).dot(c.T)) # Invariance under inversion spds_inv = [linalg.inv(spd) for spd in spds] fre_new = my_mfd.frechet_mean(spds_inv, tol=tol) assert_array_almost_equal(fre_new, linalg.inv(fre), decimal=decimal) # Approximate Frechet mean is close to the exact one decimal = 7 tol = 0.5 * 10 ** (-decimal) # Diagonal matrices: exact Frechet mean is geometric mean diags = [] for k in xrange(n): diags.append(my_mfd.random_diagonal_spd(shape, 1e-5, 1e5)) exact_fre = np.prod(my_mfd.my_stack(diags), axis=0) ** \ (1 / float(len(diags))) app_fre = my_mfd.frechet_mean(diags, max_iter=10, tol=tol) assert_array_almost_equal(app_fre, exact_fre, decimal) # 2 matrices spd1 = my_mfd.random_spd(shape) spd2 = my_mfd.random_spd(shape) spd2_sqrt = my_mfd.sqrtm(spd2) spd2_inv_sqrt = my_mfd.inv_sqrtm(spd2) exact_fre = spd2_sqrt.dot( my_mfd.sqrtm(spd2_inv_sqrt.dot(spd1).dot(spd2_inv_sqrt))).dot(spd2_sqrt) app_fre = my_mfd.frechet_mean([spd1, spd2], tol=tol) assert_array_almost_equal(app_fre, exact_fre, decimal) # Single geodesic matrices : TODO S = np.random.rand(shape, shape) S = S + S.T times = np.empty(n, dtype=float) spds = [] for k in xrange(n): t_k = random.uniform(-2., -1.) times[k] = t_k spds.append(c.dot(my_mfd.expm(t_k * S)).dot(c.T))