コード例 #1
0
 def __init__(self, dim, scale=1.0):
     super(PoincareHalfSpaceMetric, self).__init__(dim=dim,
                                                   signature=(dim, 0))
     self.coords_type = PoincareHalfSpace.default_coords_type
     self.point_type = PoincareHalfSpace.default_point_type
     self.scale = scale
     self.poincare_ball = PoincareBall(dim=dim, scale=scale)
コード例 #2
0
 def test_coordinate(self, dim, point_a, point_b):
     metric = self.metric(dim)
     point_a_h = PoincareBall(dim).to_coordinates(gs.array(point_a), "extrinsic")
     point_b_h = PoincareBall(dim).to_coordinates(gs.array(point_b), "extrinsic")
     dist_in_ball = metric.dist(gs.array(point_a), gs.array(point_b))
     dist_in_hype = Hyperboloid(dim).metric.dist(point_a_h, point_b_h)
     self.assertAllClose(dist_in_ball, dist_in_hype)
コード例 #3
0
    def test_distance_ball_extrinsic_from_ball(self, dim, x_ball, y_ball):

        ball_manifold = PoincareBall(dim)
        space = Hyperboloid(dim)
        x_extr = ball_manifold.to_coordinates(x_ball, to_coords_type="extrinsic")
        y_extr = ball_manifold.to_coordinates(y_ball, to_coords_type="extrinsic")
        dst_ball = ball_manifold.metric.dist(x_ball, y_ball)
        dst_extr = space.metric.dist(x_extr, y_extr)
        self.assertAllClose(dst_ball, dst_extr)
コード例 #4
0
    def setUp(self):
        gs.random.seed(1234)
        self.dimension = 2

        self.extrinsic_manifold = Hyperboloid(dim=self.dimension)
        self.extrinsic_metric = self.extrinsic_manifold.metric

        self.ball_manifold = PoincareBall(dim=self.dimension)
        self.ball_metric = self.ball_manifold.metric

        self.intrinsic_manifold = Hyperboloid(dim=self.dimension,
                                              coords_type="intrinsic")
        self.intrinsic_metric = self.intrinsic_manifold.metric

        self.n_samples = 10
コード例 #5
0
 def test_extrinsic_ball_extrinsic_composition(self, dim, point_intrinsic):
     x = Hyperboloid(dim, coords_type="intrinsic").to_coordinates(
         point_intrinsic, to_coords_type="extrinsic"
     )
     x_b = Hyperboloid(dim).to_coordinates(x, to_coords_type="ball")
     x2 = PoincareBall(dim).to_coordinates(x_b, to_coords_type="extrinsic")
     self.assertAllClose(x, x2)
コード例 #6
0
    def test_exp_after_log_intrinsic_ball_extrinsic(
        self, dim, x_intrinsic, y_intrinsic
    ):
        intrinsic_manifold = Hyperboloid(dim=dim, coords_type="intrinsic")
        extrinsic_manifold = Hyperbolic(dim=dim, coords_type="extrinsic")
        ball_manifold = PoincareBall(dim)
        x_extr = intrinsic_manifold.to_coordinates(
            x_intrinsic, to_coords_type="extrinsic"
        )
        y_extr = intrinsic_manifold.to_coordinates(
            y_intrinsic, to_coords_type="extrinsic"
        )
        x_ball = extrinsic_manifold.to_coordinates(x_extr, to_coords_type="ball")
        y_ball = extrinsic_manifold.to_coordinates(y_extr, to_coords_type="ball")

        x_ball_exp_after_log = ball_manifold.metric.exp(
            ball_manifold.metric.log(y_ball, x_ball), x_ball
        )

        x_extr_a = extrinsic_manifold.metric.exp(
            extrinsic_manifold.metric.log(y_extr, x_extr), x_extr
        )
        x_extr_b = extrinsic_manifold.from_coordinates(
            x_ball_exp_after_log, from_coords_type="ball"
        )
        self.assertAllClose(x_extr_a, x_extr_b, atol=3e-4)
コード例 #7
0
ファイル: test_hyperbolic.py プロジェクト: xpennec/geomstats
 def setup_method(self):
     gs.random.seed(1234)
     self.dimension = 3
     self.space = Hyperboloid(dim=self.dimension)
     self.metric = self.space.metric
     self.ball_manifold = PoincareBall(dim=2)
     self.n_samples = 10
コード例 #8
0
def expectation_maximisation_poincare_ball():
    """Apply EM algorithm on three random data clusters."""
    dim = 2
    n_samples = 5

    cluster_1 = gs.random.uniform(low=0.2, high=0.6, size=(n_samples, dim))
    cluster_2 = gs.random.uniform(low=-0.6, high=-0.2, size=(n_samples, dim))
    cluster_3 = gs.random.uniform(low=-0.3, high=0, size=(n_samples, dim))
    cluster_3[:, 0] = -cluster_3[:, 0]

    data = gs.concatenate((cluster_1, cluster_2, cluster_3), axis=0)

    n_clusters = 3

    manifold = PoincareBall(dim=2)

    metric = manifold.metric

    EM = RiemannianEM(n_gaussians=n_clusters,
                      metric=metric,
                      initialisation_method='random')

    means, variances, mixture_coefficients = EM.fit(data=data)

    # Plot result
    plot = plot_gaussian_mixture_distribution(data,
                                              mixture_coefficients,
                                              means,
                                              variances,
                                              plot_precision=100,
                                              save_path='result.png',
                                              metric=metric)

    return plot
コード例 #9
0
 def test_predict_poincare_ball_distance(self):
     """Test the 'predict' class method using the Poincare ball distance."""
     dim = 2
     space = PoincareBall(dim=dim)
     distance = space.metric.dist
     training_dataset = gs.array([
         [1 / 2, 1 / 4],
         [1 / 2, 0],
         [1 / 2, -1 / 4],
         [-1 / 2, 1 / 4],
         [-1 / 2, 0],
         [-1 / 2, -1 / 4],
     ])
     labels = [0, 0, 0, 1, 1, 1]
     kde = KernelDensityEstimationClassifier(distance=distance,
                                             kernel="distance")
     kde.fit(training_dataset, labels)
     target_dataset = gs.array([
         [1 / 2, 1 / 5],
         [1 / 2, 0],
         [1 / 2, -1 / 5],
         [-1 / 2, 1 / 5],
         [-1 / 2, 0],
         [-1 / 2, -1 / 5],
     ])
     result = kde.predict(target_dataset)
     expected = [0, 0, 0, 1, 1, 1]
     self.assertAllClose(expected, result)
コード例 #10
0
    def __init__(
            self, dim=2, max_epochs=100,
            lr=.05, n_context=1, n_negative=2):

        self.manifold = PoincareBall(dim)
        self.max_epochs = max_epochs
        self.lr = lr
        self.n_context = n_context
        self.n_negative = n_negative
コード例 #11
0
ファイル: hyperbolic.py プロジェクト: ninamiolane/geomstats
 def __new__(cls, *args, default_coords_type='extrinsic', **kwargs):
     """Instantiate class that corresponds to the default_coords_type."""
     errors.check_parameter_accepted_values(
         default_coords_type, 'default_coords_type',
         ['extrinsic', 'ball', 'half-space'])
     if default_coords_type == 'extrinsic':
         return Hyperboloid(*args, **kwargs)
     if default_coords_type == 'ball':
         return PoincareBall(*args, **kwargs)
     return PoincareHalfSpace(*args, **kwargs)
コード例 #12
0
    def setup_method(self):
        """Set manifold, data and EM parameters."""
        self.n_samples = 5
        self.dim = 2
        self.space = PoincareBall(dim=self.dim)
        self.metric = self.space.metric
        self.initialisation_method = "random"
        self.mean_method = "batch"

        cluster_1 = gs.random.uniform(
            low=0.2, high=0.6, size=(self.n_samples, self.dim)
        )
        cluster_2 = gs.random.uniform(
            low=-0.6, high=-0.2, size=(self.n_samples, self.dim)
        )
        cluster_3 = gs.random.uniform(low=-0.3, high=0, size=(self.n_samples, self.dim))
        cluster_3 = cluster_3 * gs.array([-1.0, 1.0])

        self.n_gaussian = 3
        self.data = gs.concatenate((cluster_1, cluster_2, cluster_3), axis=0)
コード例 #13
0
 def __new__(cls, *args, default_coords_type="extrinsic", **kwargs):
     """Instantiate class that corresponds to the default_coords_type."""
     errors.check_parameter_accepted_values(
         default_coords_type,
         "default_coords_type",
         ["extrinsic", "ball", "half-space"],
     )
     if default_coords_type == "extrinsic":
         return Hyperboloid(*args, **kwargs)
     if default_coords_type == "ball":
         return PoincareBall(*args, **kwargs)
     return PoincareHalfSpace(*args, **kwargs)
コード例 #14
0
def kmean_poincare_ball():
    """Run K-means on the Poincare ball."""
    n_samples = 20
    dim = 2
    n_clusters = 2
    manifold = PoincareBall(dim=dim)
    metric = manifold.metric

    cluster_1 = gs.random.uniform(low=0.5, high=0.6, size=(n_samples, dim))
    cluster_2 = gs.random.uniform(low=0, high=-0.2, size=(n_samples, dim))
    data = gs.concatenate((cluster_1, cluster_2), axis=0)

    kmeans = RiemannianKMeans(metric=metric,
                              n_clusters=n_clusters,
                              init='random',
                              mean_method='frechet-poincare-ball'
                              )

    centroids = kmeans.fit(X=data, max_iter=100)
    labels = kmeans.predict(X=data)

    plt.figure(1)
    colors = ['red', 'blue']

    ax = visualization.plot(
        data,
        space='H2_poincare_disk',
        marker='.',
        color='black',
        point_type=manifold.point_type)

    for i in range(n_clusters):
        ax = visualization.plot(
            data[labels == i],
            ax=ax,
            space='H2_poincare_disk',
            marker='.',
            color=colors[i],
            point_type=manifold.point_type)

    ax = visualization.plot(
        centroids,
        ax=ax,
        space='H2_poincare_disk',
        marker='*',
        color='green',
        s=100,
        point_type=manifold.point_type)

    ax.set_title('Kmeans on Poincaré Ball Manifold')

    return plt
コード例 #15
0
    def setUp(self):
        """Set manifold, data and EM parameters."""
        self.n_samples = 5
        self.dim = 2
        self.space = PoincareBall(dim=self.dim)
        self.metric = self.space.metric
        self.initialisation_method = 'random'
        self.mean_method = 'frechet-poincare-ball'

        cluster_1 = gs.random.uniform(low=0.2,
                                      high=0.6,
                                      size=(self.n_samples, self.dim))
        cluster_2 = gs.random.uniform(low=-0.6,
                                      high=-0.2,
                                      size=(self.n_samples, self.dim))
        cluster_3 = gs.random.uniform(low=-0.3,
                                      high=0,
                                      size=(self.n_samples, self.dim))
        cluster_3[:, 0] = -cluster_3[:, 0]

        self.n_gaussian = 3
        self.data = gs.concatenate((cluster_1, cluster_2, cluster_3), axis=0)
コード例 #16
0
def grad_squared_distance(point_a, point_b):
    """Gradient of squared hyperbolic distance.

    Gradient of the squared distance based on the
    Ball representation according to point_a

    Parameters
    ----------
    point_a : array-like, shape=[n_samples, dim]
        First point in hyperbolic space.
    point_b : array-like, shape=[n_samples, dim]
        Second point in hyperbolic space.

    Returns
    -------
    dist : array-like, shape=[n_samples, 1]
        Geodesic squared distance between the two points.
    """
    hyperbolic_metric = PoincareBall(2).metric
    log_map = hyperbolic_metric.log(point_b, point_a)

    return -2 * log_map
コード例 #17
0
def kmean_poincare_ball():
    """Run K-means on the Poincare ball."""
    n_samples = 20
    dim = 2
    n_clusters = 2
    manifold = PoincareBall(dim=dim)
    metric = manifold.metric

    cluster_1 = gs.random.uniform(low=0.5, high=0.6, size=(n_samples, dim))
    cluster_2 = gs.random.uniform(low=0, high=-0.2, size=(n_samples, dim))
    data = gs.concatenate((cluster_1, cluster_2), axis=0)

    kmeans = RiemannianKMeans(metric=metric, n_clusters=n_clusters, init="random")

    centroids = kmeans.fit(X=data)
    labels = kmeans.predict(X=data)

    plt.figure(1)
    colors = ["red", "blue"]

    ax = visualization.plot(
        data,
        space="H2_poincare_disk",
        marker=".",
        color="black",
        point_type=manifold.point_type,
    )

    for i in range(n_clusters):
        ax = visualization.plot(
            data[labels == i],
            ax=ax,
            space="H2_poincare_disk",
            marker=".",
            color=colors[i],
            point_type=manifold.point_type,
        )

    ax = visualization.plot(
        centroids,
        ax=ax,
        space="H2_poincare_disk",
        marker="*",
        color="green",
        s=100,
        point_type=manifold.point_type,
    )

    ax.set_title("Kmeans on Poincaré Ball Manifold")

    return plt
コード例 #18
0
    def _expectation(self, data):
        """Update the posterior probabilities.

        Parameters
        ----------
        data : array-like, shape=[n_samples, n_features]
            Training data, where n_samples is the number of samples and
            n_features is the number of features.
        """
        probability_distribution_function = \
            PoincareBall.gmm_pdf(
                data, self.means, self.variances,
                norm_func=self.metric.find_normalization_factor,
                metric=self.metric,
                variances_range=self.variances_range,
                norm_func_var=self.normalization_factor_var)

        if gs.isnan(probability_distribution_function.mean()):
            logging.warning('EXPECTATION : Probability distribution function'
                            'contain elements that are not numbers')

        num_normalized_pdf = gs.einsum('j,...j->...j',
                                       self.mixture_coefficients,
                                       probability_distribution_function)
        valid_pdf_condition = gs.amin(gs.sum(num_normalized_pdf, -1))

        if valid_pdf_condition <= PDF_TOL:

            num_normalized_pdf[gs.sum(num_normalized_pdf, -1) <= PDF_TOL] = 1

        sum_pdf = gs.sum(num_normalized_pdf, -1)
        posterior_probabilities =\
            gs.einsum('...i,...->...i', num_normalized_pdf, 1 / sum_pdf)

        if gs.any(gs.mean(posterior_probabilities)) is None:

            logging.warning('EXPECTATION : posterior probabilities '
                            'contain elements that are not numbers.')

        if 1 - SUM_CHECK_PDF >= gs.mean(gs.sum(posterior_probabilities,
                                               1)) >= 1 + SUM_CHECK_PDF:

            logging.warning('EXPECTATION : posterior probabilities '
                            'do not sum to 1.')

        if gs.any(gs.sum(posterior_probabilities, 0) < PDF_TOL):
            logging.warning('EXPECTATION : Gaussian got no elements '
                            '(precision error) reinitialize')
            posterior_probabilities[posterior_probabilities == 0] = PDF_TOL

        return posterior_probabilities
コード例 #19
0
    def test_distance_ball_extrinsic_intrinsic(self, dim, x_intrinsic, y_intrinsic):

        intrinsic_manifold = Hyperboloid(dim, coords_type="intrinsic")
        extrinsic_manifold = Hyperboloid(dim, coords_type="extrinsic")
        x_extr = intrinsic_manifold.to_coordinates(
            x_intrinsic, to_coords_type="extrinsic"
        )
        y_extr = intrinsic_manifold.to_coordinates(
            y_intrinsic, to_coords_type="extrinsic"
        )
        x_ball = extrinsic_manifold.to_coordinates(x_extr, to_coords_type="ball")
        y_ball = extrinsic_manifold.to_coordinates(y_extr, to_coords_type="ball")
        dst_ball = PoincareBall(dim).metric.dist(x_ball, y_ball)
        dst_extr = extrinsic_manifold.metric.dist(x_extr, y_extr)

        self.assertAllClose(dst_ball, dst_extr)
コード例 #20
0
    def test_distance_ball_extrinsic_from_extr_4_dim(self):
        x_int = gs.array([10, 0.2, 3, 4])
        y_int = gs.array([1, 6, 2.0, 1])

        ball_manifold = PoincareBall(4)
        extrinsic_manifold = Hyperboloid(4)

        ball_metric = ball_manifold.metric
        extrinsic_metric = extrinsic_manifold.metric

        x_extr = extrinsic_manifold.from_coordinates(
            x_int, from_coords_type="intrinsic")
        y_extr = extrinsic_manifold.from_coordinates(
            y_int, from_coords_type="intrinsic")
        x_ball = extrinsic_manifold.to_coordinates(x_extr,
                                                   to_coords_type="ball")
        y_ball = extrinsic_manifold.to_coordinates(y_extr,
                                                   to_coords_type="ball")
        dst_ball = ball_metric.dist(x_ball, y_ball)
        dst_extr = extrinsic_metric.dist(x_extr, y_extr)

        self.assertAllClose(dst_ball, dst_extr)
コード例 #21
0
    def test_distance_ball_extrinsic_from_extr_4_dim(self):
        x_int = gs.array([[10, 0.2, 3, 4]])
        y_int = gs.array([[1, 6, 2., 1]])

        ball_manifold = PoincareBall(4)
        extrinsic_manifold = Hyperboloid(4)

        ball_metric = ball_manifold.metric
        extrinsic_metric = extrinsic_manifold.metric

        x_extr = extrinsic_manifold.from_coordinates(
            x_int, from_coords_type='intrinsic')
        y_extr = extrinsic_manifold.from_coordinates(
            y_int, from_coords_type='intrinsic')
        x_ball = extrinsic_manifold.to_coordinates(
            x_extr, to_coords_type='ball')
        y_ball = extrinsic_manifold.to_coordinates(
            y_extr, to_coords_type='ball')
        dst_ball = ball_metric.dist(x_ball, y_ball)
        dst_extr = extrinsic_metric.dist(x_extr, y_extr)
        # TODO(nmiolane): Remove this when ball is properly vectorized
        dst_extr = gs.to_ndarray(dst_extr, to_ndim=2, axis=1)

        self.assertAllClose(dst_ball, dst_extr)
コード例 #22
0
    def setUp(self):
        self.manifold = PoincareBall(2)
        self.metric = self.manifold.metric

        self.hyperboloid_manifold = Hyperboloid(2)
        self.hyperboloid_metric = self.hyperboloid_manifold.metric
コード例 #23
0
class TestPoincareBallMethods(geomstats.tests.TestCase):
    def setUp(self):
        self.manifold = PoincareBall(2)
        self.metric = self.manifold.metric

        self.hyperboloid_manifold = Hyperboloid(2)
        self.hyperboloid_metric = self.hyperboloid_manifold.metric

    def test_squared_dist(self):
        point_a = gs.array([-0.3, 0.7])
        point_b = gs.array([0.2, 0.5])

        distance_a_b = self.metric.dist(point_a, point_b)
        squared_distance = self.metric.squared_dist(point_a, point_b)

        # TODO(nmiolane):
        # Remove this line when poincare ball is properly vectorized
        squared_distance = gs.to_ndarray(squared_distance, to_ndim=2, axis=1)

        self.assertAllClose(distance_a_b**2, squared_distance, atol=1e-8)

    @geomstats.tests.np_and_pytorch_only
    def test_coordinates(self):
        point_a = gs.array([-0.3, 0.7])
        point_b = gs.array([0.2, 0.5])

        point_a_h =\
            self.manifold.to_coordinates(point_a, 'extrinsic')
        point_b_h =\
            self.manifold.to_coordinates(point_b, 'extrinsic')

        dist_in_ball =\
            self.metric.dist(point_a, point_b)
        dist_in_hype =\
            self.hyperboloid_metric.dist(point_a_h, point_b_h)

        # TODO(ninamiolane): Remove this to_ndarray when poincare_ball
        # is properly vectorized
        dist_in_hype = gs.to_ndarray(dist_in_hype, to_ndim=2, axis=1)

        self.assertAllClose(dist_in_ball, dist_in_hype, atol=1e-8)

    def test_dist_poincare(self):

        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([0.5, -0.5])

        dist_a_b =\
            self.manifold.metric.dist(point_a, point_b)

        result = dist_a_b
        expected = gs.array([[2.887270927429199]])

        self.assertAllClose(result, expected)

    def test_dist_vectorization(self):
        point_a = gs.array([0.2, 0.5])
        point_b = gs.array([[0.3, -0.5], [0.2, 0.2]])

        dist_a_b =\
            self.manifold.metric.dist(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.dist(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.concatenate(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_mobius_vectorization(self):
        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([[0.5, -0.3], [0.3, 0.4]])

        dist_a_b =\
            self.manifold.metric.mobius_add(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.mobius_add(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.concatenate(result, axis=0)
        self.assertAllClose(result_vect, result)

        dist_a_b =\
            self.manifold.metric.mobius_add(point_b, point_a)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.mobius_add(point_b[i], point_a)
             for i in range(len(point_b))]
        result = gs.concatenate(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_log_vectorization(self):
        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([[0.5, -0.5], [0.4, 0.4]])

        dist_a_b =\
            self.manifold.metric.log(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.log(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.concatenate(result, axis=0)
        self.assertAllClose(result_vect, result)

        dist_a_b =\
            self.manifold.metric.log(point_b, point_a)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.log(point_b[i], point_a)
             for i in range(len(point_b))]
        result = gs.concatenate(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_exp_vectorization(self):
        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([[0.5, -0.5], [0.4, 0.4]])

        dist_a_b =\
            self.manifold.metric.exp(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.exp(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.concatenate(result, axis=0)
        self.assertAllClose(result_vect, result)

        dist_a_b =\
            self.manifold.metric.exp(point_b, point_a)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.exp(point_b[i], point_a)
             for i in range(len(point_b))]
        result = gs.concatenate(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_log_poincare(self):

        point = gs.array([[0.3, 0.5]])
        base_point = gs.array([[0.3, 0.3]])

        result = self.manifold.metric.log(point, base_point)
        expected = gs.array([[-0.01733576, 0.21958634]])

        self.manifold.metric.coords_type = 'extrinsic'
        self.assertAllClose(result, expected)

    def test_belong_true_poincare(self):
        point = gs.array([[0.3, 0.5]])
        belong = self.manifold.belongs(point)
        self.assertTrue(belong)

    def test_belong_false_poincare(self):
        point = gs.array([[1.2, 0.5]])
        belong = self.manifold.belongs(point)
        self.assertFalse(belong)

    def test_exp_poincare(self):

        point = gs.array([[0.3, 0.5]])
        base_point = gs.array([[0.3, 0.3]])

        tangent_vec = self.manifold.metric.log(point, base_point)
        result = self.manifold.metric.exp(tangent_vec, base_point)

        self.manifold.metric.coords_type = 'extrinsic'
        self.assertAllClose(result, point)

    def test_ball_retraction(self):
        x = gs.array([[0.5, 0.6], [0.2, -0.1], [0.2, -0.4]])
        y = gs.array([[0.3, 0.5], [0.3, -0.6], [0.3, -0.3]])

        ball_metric = self.manifold.metric
        tangent_vec = ball_metric.log(y, x)
        ball_metric.retraction(tangent_vec, x)
コード例 #24
0
class TestPoincareBall(geomstats.tests.TestCase):
    def setUp(self):
        self.manifold = PoincareBall(2)
        self.metric = self.manifold.metric

        self.hyperboloid_manifold = Hyperboloid(2)
        self.hyperboloid_metric = self.hyperboloid_manifold.metric

    def test_squared_dist(self):
        point_a = gs.array([-0.3, 0.7])
        point_b = gs.array([0.2, 0.5])

        distance_a_b = self.metric.dist(point_a, point_b)
        squared_distance = self.metric.squared_dist(point_a, point_b)

        self.assertAllClose(distance_a_b**2, squared_distance, atol=1e-8)

    @geomstats.tests.np_and_pytorch_only
    def test_coordinates(self):
        point_a = gs.array([-0.3, 0.7])
        point_b = gs.array([0.2, 0.5])

        point_a_h =\
            self.manifold.to_coordinates(point_a, 'extrinsic')
        point_b_h =\
            self.manifold.to_coordinates(point_b, 'extrinsic')

        dist_in_ball =\
            self.metric.dist(point_a, point_b)
        dist_in_hype =\
            self.hyperboloid_metric.dist(point_a_h, point_b_h)

        self.assertAllClose(dist_in_ball, dist_in_hype, atol=1e-8)

    def test_dist_poincare(self):

        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([0.5, -0.5])

        dist_a_b =\
            self.manifold.metric.dist(point_a, point_b)

        result = dist_a_b
        expected = 2.887270927429199

        self.assertAllClose(result, expected)

    def test_dist_vectorization(self):
        point_a = gs.array([0.2, 0.5])
        point_b = gs.array([[0.3, -0.5], [0.2, 0.2]])

        dist_a_b =\
            self.manifold.metric.dist(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.dist(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.stack(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_dist_broadcast(self):

        point_a = gs.array([[0.2, 0.5], [0.3, 0.1]])
        point_b = gs.array([[0.3, -0.5], [0.2, 0.2]])
        point_c = gs.array([[0.2, 0.3], [0.5, 0.5], [-0.4, 0.1]])
        point_d = gs.array([0.1, 0.2, 0.3])

        dist_a_b =\
            self.manifold.metric.dist_broadcast(point_a, point_b)

        dist_b_c = gs.flatten(
            self.manifold.metric.dist_broadcast(point_b, point_c))

        result_vect = gs.concatenate((dist_a_b, dist_b_c), axis=0)

        result_a_b =\
            [self.manifold.metric.dist_broadcast(point_a[i], point_b[i])
             for i in range(len(point_b))]

        result_b_c = \
            [self.manifold.metric.dist_broadcast(point_b[i], point_c[j])
             for i in range(len(point_b))
             for j in range(len(point_c))
             ]
        result = result_a_b + result_b_c
        result = gs.stack(result, axis=0)

        self.assertAllClose(result_vect, result)
        with self.assertRaises(ValueError):
            self.manifold.metric.dist_broadcast(point_a, point_d)

    @geomstats.tests.np_and_pytorch_only
    def test_dist_pairwise(self):

        point = gs.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.5]])

        result = self.manifold.metric.dist_pairwise(point)

        expected = gs.array([[0., 0.65821943, 1.34682524],
                             [0.65821943, 0., 0.71497076],
                             [1.34682524, 0.71497076, 0.]])

        self.assertAllClose(result, expected, rtol=1e-3)

    def test_mobius_vectorization(self):
        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([[0.5, -0.3], [0.3, 0.4]])

        dist_a_b =\
            self.manifold.metric.mobius_add(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.mobius_add(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.stack(result, axis=0)
        self.assertAllClose(result_vect, result)

        dist_a_b =\
            self.manifold.metric.mobius_add(point_b, point_a)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.mobius_add(point_b[i], point_a)
             for i in range(len(point_b))]
        result = gs.stack(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_log_vectorization(self):
        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([[0.5, -0.5], [0.4, 0.4]])

        dist_a_b =\
            self.manifold.metric.log(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.log(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.stack(result, axis=0)
        self.assertAllClose(result_vect, result)

        dist_a_b =\
            self.manifold.metric.log(point_b, point_a)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.log(point_b[i], point_a)
             for i in range(len(point_b))]
        result = gs.stack(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_exp_vectorization(self):
        point_a = gs.array([0.5, 0.5])
        point_b = gs.array([[0.0, 0.0], [0.5, -0.5], [0.4, 0.4]])

        dist_a_b =\
            self.manifold.metric.exp(point_a, point_b)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.exp(point_a, point_b[i])
             for i in range(len(point_b))]
        result = gs.stack(result, axis=0)
        self.assertAllClose(result_vect, result)

        dist_a_b =\
            self.manifold.metric.exp(point_b, point_a)

        result_vect = dist_a_b
        result =\
            [self.manifold.metric.exp(point_b[i], point_a)
             for i in range(len(point_b))]
        result = gs.stack(result, axis=0)
        self.assertAllClose(result_vect, result)

    def test_log_poincare(self):

        point = gs.array([0.3, 0.5])
        base_point = gs.array([0.3, 0.3])

        result = self.manifold.metric.log(point, base_point)
        expected = gs.array([-0.01733576, 0.21958634])

        self.manifold.metric.coords_type = 'extrinsic'
        self.assertAllClose(result, expected)

    def test_belong_true_poincare(self):
        point = gs.array([0.3, 0.5])
        belong = self.manifold.belongs(point)
        self.assertTrue(belong)

    def test_belong_false_poincare(self):
        point = gs.array([1.2, 0.5])
        belong = self.manifold.belongs(point)
        self.assertFalse(belong)

    def test_projection(self):
        point = gs.array([1.2, 0.5])
        projected_point = self.manifold.projection(point)
        self.assertTrue(gs.sum(projected_point * projected_point) < 1.)

    def test_exp_poincare(self):

        point = gs.array([0.3, 0.5])
        base_point = gs.array([0.3, 0.3])

        tangent_vec = self.manifold.metric.log(point, base_point)
        result = self.manifold.metric.exp(tangent_vec, base_point)

        self.manifold.metric.coords_type = 'extrinsic'
        self.assertAllClose(result, point)

    def test_ball_retraction(self):
        x = gs.array([[0.5, 0.6], [0.2, -0.1], [0.2, -0.4]])
        y = gs.array([[0.3, 0.5], [0.3, -0.6], [0.3, -0.3]])

        ball_metric = self.manifold.metric
        tangent_vec = ball_metric.log(y, x)
        ball_metric.retraction(tangent_vec, x)
コード例 #25
0
class TestEM(geomstats.tests.TestCase):
    """Class for testing Expectation Maximization."""
    def setUp(self):
        """Set manifold, data and EM parameters."""
        self.n_samples = 5
        self.dim = 2
        self.space = PoincareBall(dim=self.dim)
        self.metric = self.space.metric
        self.initialisation_method = 'random'
        self.mean_method = 'batch'

        cluster_1 = gs.random.uniform(low=0.2,
                                      high=0.6,
                                      size=(self.n_samples, self.dim))
        cluster_2 = gs.random.uniform(low=-0.6,
                                      high=-0.2,
                                      size=(self.n_samples, self.dim))
        cluster_3 = gs.random.uniform(low=-0.3,
                                      high=0,
                                      size=(self.n_samples, self.dim))
        cluster_3 = cluster_3 * gs.array([-1., 1.])

        self.n_gaussian = 3
        self.data = gs.concatenate((cluster_1, cluster_2, cluster_3), axis=0)

    @geomstats.tests.np_only
    def test_fit_init_kmeans(self):
        """Test fitting data into a GMM."""
        gmm_learning = RiemannianEM(
            metric=self.metric,
            n_gaussians=self.n_gaussian,
            initialisation_method=self.initialisation_method)

        means, variances, coefficients = gmm_learning.fit(self.data)

        self.assertTrue((coefficients < 1).all() and (coefficients > 0).all())
        self.assertTrue((variances < 1).all() and (variances > 0).all())
        self.assertTrue(self.space.belongs(means).all())

        gmm_learning = RiemannianEM(metric=self.metric,
                                    n_gaussians=self.n_gaussian,
                                    initialisation_method='kmeans')

        means, variances, coefficients = gmm_learning.fit(self.data)

        self.assertTrue((coefficients < 1).all() and (coefficients > 0).all())
        self.assertTrue((variances < 1).all() and (variances > 0).all())
        self.assertTrue(self.space.belongs(means).all())

    @geomstats.tests.np_only
    def test_fit_init_random(self):
        """Test fitting data into a GMM."""
        gmm_learning = RiemannianEM(
            metric=self.metric,
            n_gaussians=self.n_gaussian,
            initialisation_method=self.initialisation_method)

        means, variances, coefficients = gmm_learning.fit(self.data)

        self.assertTrue((coefficients < 1).all() and (coefficients > 0).all())
        self.assertTrue((variances < 1).all() and (variances > 0).all())
        self.assertTrue(self.space.belongs(means).all())

        gmm_learning = RiemannianEM(metric=self.metric,
                                    n_gaussians=self.n_gaussian,
                                    initialisation_method='random')

        means, variances, coefficients = gmm_learning.fit(self.data)

        self.assertTrue((coefficients < 1).all() and (coefficients > 0).all())
        self.assertTrue((variances < 1).all() and (variances > 0).all())
        self.assertTrue(self.space.belongs(means).all())

    def test_weighted_frechet_mean(self):
        """Test for weighted mean."""
        data = gs.array([[0.1, 0.2], [0.25, 0.35]])
        weights = gs.array([3., 1.])
        mean_o = FrechetMean(metric=self.metric, point_type='vector', lr=1.)
        mean_o.fit(data, weights=weights)
        result = mean_o.estimate_
        expected = self.metric.exp(
            weights[1] / gs.sum(weights) * self.metric.log(data[1], data[0]),
            data[0])
        self.assertAllClose(result, expected)

    @geomstats.tests.np_and_pytorch_only
    def test_normalization_factor(self):
        """Test for Gaussian distribution normalization factor."""
        gmm = RiemannianEM(self.metric)
        variances_range, normalization_factor_var, phi_inv_var = \
            gmm.normalization_factor_init(
                gs.arange(ZETA_LOWER_BOUND, ZETA_UPPER_BOUND, ZETA_STEP))
        self.assertAllClose(normalization_factor_var[4], 0.00291884, TOLERANCE)
        self.assertAllClose(phi_inv_var[3], 0.00562326, TOLERANCE)

        variances_test = gs.array([0.8, 1.2])
        norm_factor_test = find_normalization_factor(variances_test,
                                                     variances_range,
                                                     normalization_factor_var)
        norm_factor_verdict = gs.array([0.79577319, 2.3791778])
        self.assertAllClose(norm_factor_test, norm_factor_verdict, TOLERANCE)

        norm_factor_test2 = self.metric.normalization_factor(variances_test)
        self.assertAllClose(norm_factor_test2, norm_factor_verdict, TOLERANCE)

        norm_factor_test3, norm_factor_gradient_test = \
            self.metric.norm_factor_gradient(variances_test)
        norm_factor_gradient_verdict = gs.array([3.0553115709, 2.53770926])
        self.assertAllClose(norm_factor_test3, norm_factor_verdict, TOLERANCE)
        self.assertAllClose(norm_factor_gradient_test,
                            norm_factor_gradient_verdict, TOLERANCE)

        find_var_test = find_variance_from_index(
            gs.array([0.5, 0.4, 0.3, 0.2]), variances_range, phi_inv_var)
        find_var_verdict = gs.array([0.481, 0.434, 0.378, 0.311])
        self.assertAllClose(find_var_test, find_var_verdict, TOLERANCE)

    @geomstats.tests.np_only
    def test_fit_init_random_sphere(self):
        """Test fitting data into a GMM."""
        space = Hypersphere(2)
        gmm_learning = RiemannianEM(
            metric=space.metric,
            n_gaussians=2,
            initialisation_method=self.initialisation_method)

        means = space.random_uniform(2)
        cluster_1 = space.random_von_mises_fisher(mu=means[0],
                                                  kappa=20,
                                                  n_samples=140)
        cluster_2 = space.random_von_mises_fisher(mu=means[1],
                                                  kappa=20,
                                                  n_samples=140)

        data = gs.concatenate((cluster_1, cluster_2), axis=0)
        means, variances, coefficients = gmm_learning.fit(data)

        self.assertTrue((coefficients < 1).all() and (coefficients > 0).all())
        self.assertTrue((variances < 1).all() and (variances > 0).all())
        self.assertTrue(space.belongs(means).all())
コード例 #26
0
 def test_ball_extrinsic_ball(self, dim, x_ball):
     x_extrinsic = PoincareBall(dim).to_coordinates(
         x_ball, to_coords_type="extrinsic"
     )
     result = self.space(dim).to_coordinates(x_extrinsic, to_coords_type="ball")
     self.assertAllClose(result, x_ball)
コード例 #27
0
class TestHyperbolicCoords(geomstats.tests.TestCase):
    def setUp(self):
        gs.random.seed(1234)
        self.dimension = 2

        self.extrinsic_manifold = Hyperboloid(dim=self.dimension)
        self.extrinsic_metric = self.extrinsic_manifold.metric

        self.ball_manifold = PoincareBall(dim=self.dimension)
        self.ball_metric = self.ball_manifold.metric

        self.intrinsic_manifold = Hyperboloid(dim=self.dimension,
                                              coords_type="intrinsic")
        self.intrinsic_metric = self.intrinsic_manifold.metric

        self.n_samples = 10

    def test_extrinsic_ball_extrinsic(self):
        x_in = gs.array([0.5, 7])
        x = self.intrinsic_manifold.to_coordinates(x_in,
                                                   to_coords_type="extrinsic")
        x_b = self.extrinsic_manifold.to_coordinates(x, to_coords_type="ball")
        x2 = self.ball_manifold.to_coordinates(x_b, to_coords_type="extrinsic")
        self.assertAllClose(x, x2)

    def test_belongs_intrinsic(self):
        x_in = gs.array([0.5, 7])
        is_in = self.intrinsic_manifold.belongs(x_in)
        self.assertTrue(is_in)

    def test_belongs_extrinsic(self):
        x_true = self.intrinsic_manifold.to_coordinates(
            gs.array([0.5, 7]), "extrinsic")
        x_false = gs.array([0.5, 7, 3.0])
        is_in = self.extrinsic_manifold.belongs(x_true)
        self.assertTrue(is_in)
        is_out = self.extrinsic_manifold.belongs(x_false)
        self.assertFalse(is_out)

    def test_belongs_ball(self):
        x_true = gs.array([0.5, 0.5])
        x_false = gs.array([0.8, 0.8])
        is_in = self.ball_manifold.belongs(x_true)
        self.assertTrue(is_in)
        is_out = self.ball_manifold.belongs(x_false)
        self.assertFalse(is_out)

    def test_extrinsic_half_plane_extrinsic(self):
        x_in = gs.array([0.5, 7], dtype=gs.float64)
        x = self.intrinsic_manifold.to_coordinates(x_in,
                                                   to_coords_type="extrinsic")
        x_up = self.extrinsic_manifold.to_coordinates(
            x, to_coords_type="half-space")

        x2 = Hyperbolic.change_coordinates_system(x_up, "half-space",
                                                  "extrinsic")
        self.assertAllClose(x, x2)

    def test_intrinsic_extrinsic_intrinsic(self):
        x_intr = gs.array([0.5, 7])
        x_extr = self.intrinsic_manifold.to_coordinates(
            x_intr, to_coords_type="extrinsic")
        x_intr2 = self.extrinsic_manifold.to_coordinates(
            x_extr, to_coords_type="intrinsic")
        self.assertAllClose(x_intr, x_intr2)

    def test_ball_extrinsic_ball(self):
        x = gs.array([0.5, 0.2])
        x_e = self.ball_manifold.to_coordinates(x, to_coords_type="extrinsic")
        x2 = self.extrinsic_manifold.to_coordinates(x_e, to_coords_type="ball")
        self.assertAllClose(x, x2)

    def test_distance_ball_extrinsic_from_ball(self):
        x_ball = gs.array([0.7, 0.2])
        y_ball = gs.array([0.2, 0.2])
        x_extr = self.ball_manifold.to_coordinates(x_ball,
                                                   to_coords_type="extrinsic")
        y_extr = self.ball_manifold.to_coordinates(y_ball,
                                                   to_coords_type="extrinsic")
        dst_ball = self.ball_metric.dist(x_ball, y_ball)
        dst_extr = self.extrinsic_metric.dist(x_extr, y_extr)

        self.assertAllClose(dst_ball, dst_extr)

    def test_distance_ball_extrinsic_from_extr(self):
        x_int = gs.array([10, 0.2])
        y_int = gs.array([1, 6.0])
        x_extr = self.intrinsic_manifold.to_coordinates(
            x_int, to_coords_type="extrinsic")
        y_extr = self.intrinsic_manifold.to_coordinates(
            y_int, to_coords_type="extrinsic")
        x_ball = self.extrinsic_manifold.to_coordinates(x_extr,
                                                        to_coords_type="ball")
        y_ball = self.extrinsic_manifold.to_coordinates(y_extr,
                                                        to_coords_type="ball")
        dst_ball = self.ball_metric.dist(x_ball, y_ball)
        dst_extr = self.extrinsic_metric.dist(x_extr, y_extr)

        self.assertAllClose(dst_ball, dst_extr)

    def test_distance_ball_extrinsic_from_extr_4_dim(self):
        x_int = gs.array([10, 0.2, 3, 4])
        y_int = gs.array([1, 6, 2.0, 1])

        ball_manifold = PoincareBall(4)
        extrinsic_manifold = Hyperboloid(4)

        ball_metric = ball_manifold.metric
        extrinsic_metric = extrinsic_manifold.metric

        x_extr = extrinsic_manifold.from_coordinates(
            x_int, from_coords_type="intrinsic")
        y_extr = extrinsic_manifold.from_coordinates(
            y_int, from_coords_type="intrinsic")
        x_ball = extrinsic_manifold.to_coordinates(x_extr,
                                                   to_coords_type="ball")
        y_ball = extrinsic_manifold.to_coordinates(y_extr,
                                                   to_coords_type="ball")
        dst_ball = ball_metric.dist(x_ball, y_ball)
        dst_extr = extrinsic_metric.dist(x_extr, y_extr)

        self.assertAllClose(dst_ball, dst_extr)

    def test_log_exp_ball_extrinsic_from_extr(self):
        """Compare log exp in different parameterizations."""
        x_int = gs.array([4.0, 0.2])
        y_int = gs.array([3.0, 3])
        x_extr = self.intrinsic_manifold.to_coordinates(
            x_int, to_coords_type="extrinsic")
        y_extr = self.intrinsic_manifold.to_coordinates(
            y_int, to_coords_type="extrinsic")
        x_ball = self.extrinsic_manifold.to_coordinates(x_extr,
                                                        to_coords_type="ball")
        y_ball = self.extrinsic_manifold.to_coordinates(y_extr,
                                                        to_coords_type="ball")

        x_ball_log_exp = self.ball_metric.exp(
            self.ball_metric.log(y_ball, x_ball), x_ball)

        x_extr_a = self.extrinsic_metric.exp(
            self.extrinsic_metric.log(y_extr, x_extr), x_extr)
        x_extr_b = self.extrinsic_manifold.from_coordinates(
            x_ball_log_exp, from_coords_type="ball")
        self.assertAllClose(x_extr_a, x_extr_b, atol=3e-4)

    def test_log_exp_ball(self):
        x = gs.array([0.1, 0.2])
        y = gs.array([0.2, 0.5])

        log = self.ball_metric.log(point=y, base_point=x)
        exp = self.ball_metric.exp(tangent_vec=log, base_point=x)
        self.assertAllClose(exp, y)

    def test_log_exp_ball_vectorization(self):
        x = gs.array([0.1, 0.2])
        y = gs.array([[0.2, 0.5], [0.1, 0.7]])

        log = self.ball_metric.log(y, x)
        exp = self.ball_metric.exp(log, x)
        self.assertAllClose(exp, y)

    def test_log_exp_ball_null_tangent(self):
        x = gs.array([[0.1, 0.2], [0.1, 0.2]])
        tangent_vec = gs.array([[0.0, 0.0], [0.0, 0.0]])
        exp = self.ball_metric.exp(tangent_vec, x)
        self.assertAllClose(exp, x)
コード例 #28
0
class PoincareHalfSpaceMetric(RiemannianMetric):
    """Class for the metric of the n-dimensional hyperbolic space.

    Class for the metric of the n-dimensional hyperbolic space
    as embedded in the Poincaré half space model.

    Parameters
    ----------
    dim : int
        Dimension of the hyperbolic space.
    scale : int
        Scale of the hyperbolic space, defined as the set of points
        in Minkowski space whose squared norm is equal to -scale.
        Optional, default: 1.
    """

    default_point_type = "vector"
    default_coords_type = "half-space"

    def __init__(self, dim, scale=1.0):
        super(PoincareHalfSpaceMetric, self).__init__(dim=dim,
                                                      signature=(dim, 0))
        self.coords_type = PoincareHalfSpace.default_coords_type
        self.point_type = PoincareHalfSpace.default_point_type
        self.scale = scale
        self.poincare_ball = PoincareBall(dim=dim, scale=scale)

    def inner_product(self, tangent_vec_a, tangent_vec_b, base_point):
        """Compute the inner-product of two tangent vectors at a base point.

        Parameters
        ----------
        tangent_vec_a : array-like, shape=[..., dim + 1]
            First tangent vector at base point.
        tangent_vec_b : array-like, shape=[..., dim + 1]
            Second tangent vector at base point.
        base_point : array-like, shape=[..., dim + 1]
            Point in hyperbolic space.

        Returns
        -------
        inner_prod : array-like, shape=[..., 1]
            Inner-product of the two tangent vectors.
        """
        inner_prod = gs.sum(tangent_vec_a * tangent_vec_b, axis=-1)
        inner_prod = inner_prod / base_point[..., -1]**2
        return inner_prod

    def exp(self, tangent_vec, base_point, **kwargs):
        """Compute the Riemannian exponential.

        Parameters
        ----------
        tangent_vec : array-like, shape=[...,n]
            Tangent vector at the base point in the Poincare half space.
        base_point : array-like, shape=[...,n]
            Point in the Poincare half space.

        Returns
        -------
        end_point : array-like, shape=[...,n]
            Point in the Poincare half space, reached by the geodesic
            starting from `base_point` with initial velocity `tangent_vec`
        """
        base_point_ball = self.poincare_ball.half_space_to_ball_coordinates(
            base_point)
        tangent_vec_ball = self.poincare_ball.half_space_to_ball_tangent(
            tangent_vec, base_point)
        end_point_ball = self.poincare_ball.metric.exp(tangent_vec_ball,
                                                       base_point_ball)
        end_point = self.poincare_ball.ball_to_half_space_coordinates(
            end_point_ball)
        return end_point

    def log(self, point, base_point, **kwargs):
        """Compute Riemannian logarithm of a point wrt a base point.

        Parameters
        ----------
        point : array-like, shape=[..., dim]
            Point in hyperbolic space.
        base_point : array-like, shape=[..., dim]
            Point in hyperbolic space.

        Returns
        -------
        log : array-like, shape=[..., dim]
            Tangent vector at the base point equal to the Riemannian logarithm
            of point at the base point.
        """
        point_ball = self.poincare_ball.half_space_to_ball_coordinates(point)
        base_point_ball = self.poincare_ball.half_space_to_ball_coordinates(
            base_point)
        log_ball = self.poincare_ball.metric.log(point_ball, base_point_ball)
        log = self.poincare_ball.ball_to_half_space_tangent(
            log_ball, base_point_ball)
        return log
コード例 #29
0
class TestEM(geomstats.tests.TestCase):
    """Class for testing Expectation Maximization."""
    @geomstats.tests.np_and_pytorch_only
    def setUp(self):
        """Set manifold, data and EM parameters."""
        self.n_samples = 5
        self.dim = 2
        self.space = PoincareBall(dim=self.dim)
        self.metric = self.space.metric
        self.initialisation_method = 'random'
        self.mean_method = 'frechet-poincare-ball'

        cluster_1 = gs.random.uniform(low=0.2,
                                      high=0.6,
                                      size=(self.n_samples, self.dim))
        cluster_2 = gs.random.uniform(low=-0.6,
                                      high=-0.2,
                                      size=(self.n_samples, self.dim))
        cluster_3 = gs.random.uniform(low=-0.3,
                                      high=0,
                                      size=(self.n_samples, self.dim))
        cluster_3[:, 0] = -cluster_3[:, 0]

        self.n_gaussian = 3
        self.data = gs.concatenate((cluster_1, cluster_2, cluster_3), axis=0)

    @geomstats.tests.np_only
    def test_fit(self):
        """Test fitting data into a GMM."""
        gmm_learning = RiemannianEM(
            riemannian_metric=self.metric,
            n_gaussians=self.n_gaussian,
            initialisation_method=self.initialisation_method,
            mean_method=self.mean_method)

        means, variances, coefficients = gmm_learning.fit(self.data)

        self.assertTrue((coefficients < 1).all() and (coefficients > 0).all())
        self.assertTrue((variances < 1).all() and (variances > 0).all())
        self.assertTrue(self.space.belongs(means).all())

    @geomstats.tests.np_only
    def test_weighted_frechet_mean(self):
        """Test for weighted mean."""
        data = gs.array([[0.1, 0.2], [0.25, 0.35], [-0.1, -0.2], [-0.4, 0.3]])
        weights = gs.repeat([0.5], data.shape[0])
        mean_o = FrechetMean(metric=self.metric, point_type='vector')
        mean_o.fit(data, weights)
        mean = mean_o.estimate_
        mean_verdict = [-0.03857, 0.15922]
        self.assertAllClose(mean, mean_verdict, TOLERANCE)

    @geomstats.tests.np_and_pytorch_only
    def test_normalization_factor(self):
        """Test for Gaussian distribution normalization factor."""
        variances_range,\
            normalization_factor_var,\
            phi_inv_var = \
            self.metric.normalization_factor_init(gs.arange(
                ZETA_LOWER_BOUND, ZETA_UPPER_BOUND, ZETA_STEP))
        self.assertAllClose(normalization_factor_var[4], 0.00291884, TOLERANCE)
        self.assertAllClose(phi_inv_var[3], 0.00562326, TOLERANCE)

        variances_test = gs.array([0.8, 1.2])
        norm_factor_test = self.metric.find_normalization_factor(
            variances_test, variances_range, normalization_factor_var)
        norm_factor_verdict = gs.array([0.79577319, 2.3791778])
        self.assertAllClose(norm_factor_test, norm_factor_verdict, TOLERANCE)

        norm_factor_test2 = self.metric.normalization_factor(variances_test)
        self.assertAllClose(norm_factor_test2, norm_factor_verdict, TOLERANCE)

        norm_factor_test3, norm_factor_gradient_test = \
            self.metric.norm_factor_gradient(variances_test)
        norm_factor_gradient_verdict = gs.array([3.0553115709, 2.53770926])
        self.assertAllClose(norm_factor_test3, norm_factor_verdict, TOLERANCE)
        self.assertAllClose(norm_factor_gradient_test,
                            norm_factor_gradient_verdict, TOLERANCE)

        find_var_test = self.metric.find_variance_from_index(
            gs.array([0.5, 0.4, 0.3, 0.2]), variances_range, phi_inv_var)
        find_var_verdict = gs.array([0.481, 0.434, 0.378, 0.311])
        self.assertAllClose(find_var_test, find_var_verdict, TOLERANCE)
コード例 #30
0
def main():
    """Learning Poincaré graph embedding.

    Learns Poincaré Ball embedding by using Riemannian
    gradient descent algorithm.
    """
    gs.random.seed(1234)
    dim = 2
    max_epochs = 100
    lr = .05
    n_negative = 2
    context_size = 1
    karate_graph = gdp.Graph(
        graph_matrix_path='examples/data/graph_karate/karate.txt',
        labels_path='examples/data/graph_karate/karate_labels.txt')

    nb_vertices_by_edges =\
        [len(e_2) for _, e_2 in karate_graph.edges.items()]
    logging.info('Number of edges: %s', len(karate_graph.edges))
    logging.info('Mean vertices by edges: %s',
                 (sum(nb_vertices_by_edges, 0) / len(karate_graph.edges)))

    negative_table_parameter = 5
    negative_sampling_table = []

    for i, nb_v in enumerate(nb_vertices_by_edges):
        negative_sampling_table +=\
            ([i] * int((nb_v**(3. / 4.))) * negative_table_parameter)

    negative_sampling_table = gs.array(negative_sampling_table)
    random_walks = karate_graph.random_walk()
    embeddings = gs.random.normal(size=(karate_graph.n_nodes, dim))
    embeddings = embeddings * 0.2

    hyperbolic_manifold = PoincareBall(2)

    colors = {1: 'b', 2: 'r'}
    for epoch in range(max_epochs):
        total_loss = []
        for path in random_walks:

            for example_index, one_path in enumerate(path):
                context_index = path[max(0, example_index - context_size
                                         ):min(example_index +
                                               context_size, len(path))]
                negative_index =\
                    gs.random.randint(negative_sampling_table.shape[0],
                                      size=(len(context_index),
                                      n_negative))
                negative_index = negative_sampling_table[negative_index]

                example_embedding = embeddings[one_path]

                for one_context_i, one_negative_i in zip(
                        context_index, negative_index):
                    context_embedding = embeddings[one_context_i]
                    negative_embedding = embeddings[one_negative_i]
                    l, g_ex = loss(example_embedding, context_embedding,
                                   negative_embedding, hyperbolic_manifold)
                    total_loss.append(l)

                    example_to_update = embeddings[one_path]
                    embeddings[one_path] = hyperbolic_manifold.metric.exp(
                        -lr * g_ex, example_to_update)

        logging.info('iteration %d loss_value %f', epoch,
                     sum(total_loss, 0) / len(total_loss))

    circle = visualization.PoincareDisk(point_type='ball')
    plt.figure()
    ax = plt.subplot(111)
    circle.add_points(gs.array([[0, 0]]))
    circle.set_ax(ax)
    circle.draw(ax=ax)
    for i_embedding, embedding in enumerate(embeddings):
        plt.scatter(embedding[0],
                    embedding[1],
                    c=colors[karate_graph.labels[i_embedding][0]])
    plt.show()