Beispiel #1
0
    def fit(self, X, y, X_domain, y_domain, sample_weight=None):
        """Fit (estimates) the centroids.

        Parameters
        ----------
        X : ndarray, shape (n_trials, n_channels, n_channels)
            ndarray of SPD matrices.
        y : ndarray shape (n_trials, 1)
            labels corresponding to each trial.
        sample_weight : None | ndarray shape (n_trials, 1)
            the weights of each sample from the domain. if None, each sample
            is treated with equal weights.

        Returns
        -------
        self : MDM instance
            The MDM instance.
        """
        self.classes_ = np.unique(y)
        # TODO: ajouter un test pour verifier que y et y_domain
        #       ont les meme classes

        if sample_weight is None:
            sample_weight = np.ones(X_domain.shape[0])

        if self.n_jobs == 1:
            self.target_means_ = [
                mean_covariance(X[y == label], metric=self.metric_mean)
                # sample_weight=sample_weight_target[y == l])
                for label in self.classes_
            ]

            self.domain_means_ = [
                mean_covariance(
                    X_domain[y_domain == label],
                    metric=self.metric_mean,
                    sample_weight=sample_weight[y_domain == label],
                ) for label in self.classes_
            ]
        else:
            self.target_means_ = Parallel(n_jobs=self.n_jobs)(
                delayed(mean_covariance)(X[y == label],
                                         metric=self.metric_mean) for label in
                self.classes_)  # sample_weight=sample_weight_target[y == l])
            self.domain_means_ = Parallel(n_jobs=self.n_jobs)(
                delayed(mean_covariance)(
                    X_domain[y_domain == label],
                    metric=self.metric_mean,
                    sample_weight=sample_weight[y_domain == label],
                ) for label in self.classes_)

        self.class_center_ = [
            geodesic(self.target_means_[i], self.domain_means_[i], self.L,
                     self.metric) for i, _ in enumerate(self.classes_)
        ]

        return self
Beispiel #2
0
def test_distance_wrapper_random(met, gfunc, get_covmats):
    n_trials, n_channels = 2, 5
    covmats = get_covmats(n_trials, n_channels)
    A, B = covmats[0], covmats[1]
    if gfunc is geodesic_euclid:
        Ctrue = mean_euclid(covmats)
    elif gfunc is geodesic_logeuclid:
        Ctrue = mean_logeuclid(covmats)
    elif gfunc is geodesic_riemann:
        Ctrue = mean_riemann(covmats)
    assert geodesic(A, B, 0.5, metric=met) == approx(Ctrue)
Beispiel #3
0
def test_distance_wrapper_simple(metric):
    n_channels = 3
    if metric == "euclid":
        A = 1.0 * np.eye(n_channels)
        B = 2.0 * np.eye(n_channels)
        Ctrue = 1.5 * np.eye(n_channels)
    else:
        A = 0.5 * np.eye(n_channels)
        B = 2 * np.eye(n_channels)
        Ctrue = np.eye(n_channels)
    assert geodesic(A, B, 0.5, metric=metric) == approx(Ctrue)
Beispiel #4
0
def test_geodesic_logeuclid():
    """Test riemannian geodesic when alpha = 0.5 for global function"""
    A = 0.5*np.eye(3)
    B = 2*np.eye(3)
    Ctrue = 1*np.eye(3)
    assert_array_almost_equal(geodesic(A,B,0.5,metric='logeuclid'),Ctrue)
Beispiel #5
0
def get_gram_matrices_for_images(pyramid_gram_model,
                                 image_sources,
                                 source_width=None,
                                 source_scale=None,
                                 join_mode=JoinMode.AVERAGE):

    target_grams = []
    print("Loading image files")
    image_files = image_files_from_sources(image_sources)
    for i, prepped in enumerate(
            get_images(image_files,
                       source_width=source_width,
                       source_scale=source_scale)):
        print("{} / {}...".format(i + 1, len(image_files)))
        this_grams = pyramid_gram_model.predict(prepped)
        print("got the grams!")

        # There is a bug somewhere where if the # of octaves is set to 0 the shapes of these arrays is different
        this_grams = [np.squeeze(g) for g in this_grams]

        if join_mode in {
                JoinMode.AFFINE_INVARIANT, JoinMode.LOG_EUCLIDEAN,
                JoinMode.RIEMANN
        }:
            # Add a small epsilon to the diagonals to ensure a positive definite matrix
            eps = 0.05
            this_grams = [
                g + np.identity(g.shape[0]) * eps for g in this_grams
            ]
            print(this_grams)
        if join_mode in {JoinMode.AFFINE_INVARIANT, JoinMode.RIEMANN}:
            target_grams.append(this_grams)
        else:
            if len(target_grams) == 0:
                if join_mode == JoinMode.LOG_EUCLIDEAN:
                    target_grams = [linalg.logm(gram) for gram in this_grams]
                else:
                    target_grams = this_grams
            else:
                for target_gram, this_gram in zip(target_grams, this_grams):
                    # There are likely more interesting ways to join gram matrices, including
                    # having "don't care" regions where it's not necessary to match at all. This would
                    # probably allow fusion between disparate image types to work better.
                    if join_mode == JoinMode.AVERAGE:
                        target_gram += this_gram
                    elif join_mode == JoinMode.MAX:
                        np.maximum(target_gram, this_gram, out=target_gram)
                    elif join_mode == JoinMode.LOG_EUCLIDEAN:
                        print(this_gram.shape)
                        target_gram += linalg.logm(this_gram)
                    else:
                        assert False

    # Normalize the targets
    if join_mode in {JoinMode.AVERAGE, JoinMode.LOG_EUCLIDEAN}:
        for i, target_gram in enumerate(target_grams):
            target_gram /= len(image_files)
            if join_mode == JoinMode.LOG_EUCLIDEAN:
                target_gram = linalg.expm(target_gram)
                target_gram = np.expand_dims(target_gram, -1)
                target_grams[i] = target_gram
    elif join_mode == JoinMode.AFFINE_INVARIANT:
        if len(target_grams) != 2:
            print(
                "WARNING! affine_invariant join mode requires 2 source images")
        source_grams = target_grams  # This was mis-named
        target_grams = []
        for A, B in zip(source_grams[0], source_grams[1]):
            print("A SHAPE", A.shape)
            print("B SHAPE", B.shape)
            #if len(A.shape) > 2: A = A[0]
            #if len(B.shape) > 2: B = B[0] # TODO: Fix, yo
            rootA = linalg.fractional_matrix_power(A, 0.5)
            rootAinv = linalg.fractional_matrix_power(
                A, -0.5)  # hmm... non-invertible because 0 determinant?

            internal = 0.5 * rootAinv.dot(B).dot(rootAinv)

            interpolated = rootA.dot(linalg.expm(internal)).dot(rootA)
            target_grams.append(interpolated)
    elif join_mode == JoinMode.RIEMANN:
        from pyriemann.utils import geodesic
        source_grams = target_grams  # This was mis-named
        print("Number of source grams: ", len(source_grams))
        target_grams = []
        for A, B in zip(source_grams[0], source_grams[1]):
            print("Geodesic...")
            interp = geodesic.geodesic(A, B, 0.5, 'riemann')
            print("A", A)
            print("B", B)
            print("interp", interp)
            target_grams.append(interp)

    print("Target grams shapes: ", [t.shape for t in target_grams])
    return target_grams
def test_distance_func_rand(dist, get_covmats):
    n_trials, n_channels = 2, 6
    covmats = get_covmats(n_trials, n_channels)
    A, C = covmats[0], covmats[1]
    B = geodesic(A, C, alpha=0.5)
    assert dist(A, B) < dist(A, C)