Пример #1
0
    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])
Пример #2
0
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])
Пример #3
0
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))