def setUp(self): gs.random.seed(1234) self.dimension = 3 self.space = Hyperbolic(dimension=self.dimension) self.metric = self.space.metric self.ball_manifold = Hyperbolic(dimension=2, coords_type='ball') self.n_samples = 10
def projection_to_tangent_space(self, vector, base_point): """Project a vector in the tangent space. Project a vector in Minkowski space on the tangent space of the hyperbolic space at a base point. Parameters ---------- vector : array-like, shape=[n_samples, n_disks, dimension + 1] base_point : array-like, shape=[n_samples, n_disks, dimension + 1] Returns ------- tangent_vec : array-like, shape=[n_samples, n_disks, dimension + 1] """ n_disks = base_point.shape[1] hyperbolic_space = Hyperbolic(dimension=2, point_type=self.point_type) tangent_vec = gs.stack([ Hyperbolic.projection_to_tangent_space( self=hyperbolic_space, vector=vector[:, i_disk, :], base_point=base_point[:, i_disk, :]) for i_disk in range(n_disks) ], axis=1) return tangent_vec
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)
def test_scaled_inner_product(self): base_point_intrinsic = gs.array([1, 1, 1]) base_point = self.space.intrinsic_to_extrinsic_coords( base_point_intrinsic) tangent_vec_a = gs.array([1, 2, 3, 4]) tangent_vec_b = gs.array([5, 6, 7, 8]) tangent_vec_a = self.space.projection_to_tangent_space( tangent_vec_a, base_point) tangent_vec_b = self.space.projection_to_tangent_space( tangent_vec_b, base_point) scale = 2 default_space = Hyperbolic(dimension=self.dimension) scaled_space = Hyperbolic(dimension=self.dimension, scale=2) inner_product_default_metric = \ default_space.metric.inner_product( tangent_vec_a, tangent_vec_b, base_point) inner_product_scaled_metric = \ scaled_space.metric.inner_product( tangent_vec_a, tangent_vec_b, base_point) result = inner_product_scaled_metric expected = scale ** 2 * inner_product_default_metric self.assertAllClose(result, expected)
def main(): """Perform tangent PCA at the mean.""" fig = plt.figure(figsize=(15, 5)) hyperbolic_plane = Hyperbolic(dimension=2) data = hyperbolic_plane.random_uniform(n_samples=140) mean = hyperbolic_plane.metric.mean(data) tpca = TangentPCA(metric=hyperbolic_plane.metric, n_components=2) tpca = tpca.fit(data, base_point=mean) tangent_projected_data = tpca.transform(data) geodesic_0 = hyperbolic_plane.metric.geodesic( initial_point=mean, initial_tangent_vec=tpca.components_[0]) geodesic_1 = hyperbolic_plane.metric.geodesic( initial_point=mean, initial_tangent_vec=tpca.components_[1]) n_steps = 100 t = np.linspace(-1, 1, n_steps) geodesic_points_0 = geodesic_0(t) geodesic_points_1 = geodesic_1(t) print('Coordinates of the Log of the first 5 data points at the mean, ' 'projected on the principal components:') print(tangent_projected_data[:5]) ax_var = fig.add_subplot(121) xticks = np.arange(1, 2 + 1, 1) ax_var.xaxis.set_ticks(xticks) ax_var.set_title('Explained variance') ax_var.set_xlabel('Number of Principal Components') ax_var.set_ylim((0, 1)) ax_var.plot(xticks, tpca.explained_variance_ratio_) ax = fig.add_subplot(122) visualization.plot(mean, ax, space='H2_poincare_disk', color='darkgreen', s=10) visualization.plot(geodesic_points_0, ax, space='H2_poincare_disk', linewidth=2) visualization.plot(geodesic_points_1, ax, space='H2_poincare_disk', linewidth=2) visualization.plot(data, ax, space='H2_poincare_disk', color='black', alpha=0.7) plt.show()
def setUp(self): self.n_samples = 10 self.SO3_GROUP = SpecialOrthogonal(n=3) self.SE3_GROUP = SpecialEuclidean(n=3) self.S1 = Hypersphere(dim=1) self.S2 = Hypersphere(dim=2) self.H2 = Hyperbolic(dim=2) plt.figure()
def setUp(self): gs.random.seed(1234) self.space_matrix = ProductManifold( manifolds=[Hypersphere(dimension=2), Hyperbolic(dimension=2)], default_point_type='matrix') self.space_vector = ProductManifold( manifolds=[Hypersphere(dimension=2), Hyperbolic(dimension=5)], default_point_type='vector')
class TestVisualization(geomstats.tests.TestCase): def setUp(self): self.n_samples = 10 self.SO3_GROUP = SpecialOrthogonal(n=3, point_type='vector') self.SE3_GROUP = SpecialEuclidean(n=3, point_type='vector') self.S1 = Hypersphere(dim=1) self.S2 = Hypersphere(dim=2) self.H2 = Hyperbolic(dim=2) self.H2_half_plane = PoincareHalfSpace(dim=2) plt.figure() @staticmethod def test_tutorial_matplotlib(): visualization.tutorial_matplotlib() def test_plot_points_so3(self): points = self.SO3_GROUP.random_uniform(self.n_samples) visualization.plot(points, space='SO3_GROUP') def test_plot_points_se3(self): points = self.SE3_GROUP.random_uniform(self.n_samples) visualization.plot(points, space='SE3_GROUP') @geomstats.tests.np_and_pytorch_only def test_plot_points_s1(self): points = self.S1.random_uniform(self.n_samples) visualization.plot(points, space='S1') def test_plot_points_s2(self): points = self.S2.random_uniform(self.n_samples) visualization.plot(points, space='S2') def test_plot_points_h2_poincare_disk(self): points = self.H2.random_uniform(self.n_samples) visualization.plot(points, space='H2_poincare_disk') def test_plot_points_h2_poincare_half_plane_ext(self): points = self.H2.random_uniform(self.n_samples) visualization.plot(points, space='H2_poincare_half_plane', point_type='extrinsic') def test_plot_points_h2_poincare_half_plane_none(self): points = self.H2_half_plane.random_uniform(self.n_samples) visualization.plot(points, space='H2_poincare_half_plane') def test_plot_points_h2_poincare_half_plane_hs(self): points = self.H2_half_plane.random_uniform(self.n_samples) visualization.plot(points, space='H2_poincare_half_plane', point_type='half_space') def test_plot_points_h2_klein_disk(self): points = self.H2.random_uniform(self.n_samples) visualization.plot(points, space='H2_klein_disk')
def setUp(self): self.n_samples = 10 self.SO3_GROUP = SpecialOrthogonal(n=3, point_type='vector') self.SE3_GROUP = SpecialEuclidean(n=3, point_type='vector') self.S1 = Hypersphere(dim=1) self.S2 = Hypersphere(dim=2) self.H2 = Hyperbolic(dim=2) self.H2_half_plane = PoincareHalfSpace(dim=2) plt.figure()
def test_scaled_distance(self): point_a_intrinsic = gs.array([1, 2, 3]) point_b_intrinsic = gs.array([4, 5, 6]) point_a = self.space.intrinsic_to_extrinsic_coords(point_a_intrinsic) point_b = self.space.intrinsic_to_extrinsic_coords(point_b_intrinsic) scale = 2 default_space = Hyperbolic(dimension=self.dimension) scaled_space = Hyperbolic(dimension=self.dimension, scale=2) distance_default_metric = default_space.metric.dist(point_a, point_b) distance_scaled_metric = scaled_space.metric.dist(point_a, point_b) result = distance_scaled_metric expected = scale * distance_default_metric self.assertAllClose(result, expected)
def test_exp_and_belongs(self): H2 = Hyperbolic(dimension=2) METRIC = H2.metric base_point = gs.array([1., 0., 0.]) with self.session(): self.assertTrue(gs.eval(H2.belongs(base_point))) tangent_vec = H2.projection_to_tangent_space(vector=gs.array( [1., 2., 1.]), base_point=base_point) exp = METRIC.exp(tangent_vec=tangent_vec, base_point=base_point) with self.session(): self.assertTrue(gs.eval(H2.belongs(exp)))
def setUp(self): self.n_samples = 10 self.SO3_GROUP = SpecialOrthogonal(n=3, point_type='vector') self.SE3_GROUP = SpecialEuclidean(n=3, point_type='vector') self.S1 = Hypersphere(dim=1) self.S2 = Hypersphere(dim=2) self.H2 = Hyperbolic(dim=2) self.H2_half_plane = PoincareHalfSpace(dim=2) self.M32 = Matrices(m=3, n=2) self.S32 = PreShapeSpace(k_landmarks=3, m_ambient=2) self.KS = visualization.KendallSphere() self.M33 = Matrices(m=3, n=3) self.S33 = PreShapeSpace(k_landmarks=3, m_ambient=3) self.KD = visualization.KendallDisk() plt.figure()
def setUp(self): gs.random.seed(1234) self.sphere = Hypersphere(dimension=2) self.hyperbolic = Hyperbolic(dimension=5) self.space = ProductManifold(manifolds=[self.sphere, self.hyperbolic])
def test_extrinsic_half_plane_extrinsic_composition(self, dim, point_intrinsic): x = Hyperboloid(dim, coords_type="intrinsic").to_coordinates( point_intrinsic, to_coords_type="extrinsic" ) x_up = Hyperboloid(dim).to_coordinates(x, to_coords_type="half-space") x2 = Hyperbolic.change_coordinates_system(x_up, "half-space", "extrinsic") self.assertAllClose(x, x2)
def test_scaled_squared_norm(self): base_point_intrinsic = gs.array([1, 1, 1]) base_point = self.space.intrinsic_to_extrinsic_coords( base_point_intrinsic) tangent_vec = gs.array([1, 2, 3, 4]) tangent_vec = self.space.projection_to_tangent_space( tangent_vec, base_point) scale = 2 default_space = Hyperbolic(dimension=self.dimension) scaled_space = Hyperbolic(dimension=self.dimension, scale=2) squared_norm_default_metric = default_space.metric.squared_norm( tangent_vec, base_point) squared_norm_scaled_metric = scaled_space.metric.squared_norm( tangent_vec, base_point) result = squared_norm_scaled_metric expected = scale ** 2 * squared_norm_default_metric self.assertAllClose(result, expected)
class TestVisualizationMethods(geomstats.tests.TestCase): def setUp(self): self.n_samples = 10 self.SO3_GROUP = SpecialOrthogonal(n=3) self.SE3_GROUP = SpecialEuclidean(n=3) self.S1 = Hypersphere(dim=1) self.S2 = Hypersphere(dim=2) self.H2 = Hyperbolic(dim=2) plt.figure() @geomstats.tests.np_only def test_plot_points_so3(self): points = self.SO3_GROUP.random_uniform(self.n_samples) visualization.plot(points, space='SO3_GROUP') @geomstats.tests.np_only def test_plot_points_se3(self): points = self.SE3_GROUP.random_uniform(self.n_samples) visualization.plot(points, space='SE3_GROUP') @geomstats.tests.np_only def test_plot_points_s1(self): points = self.S1.random_uniform(self.n_samples) visualization.plot(points, space='S1') @geomstats.tests.np_only def test_plot_points_s2(self): points = self.S2.random_uniform(self.n_samples) visualization.plot(points, space='S2') @geomstats.tests.np_only def test_plot_points_h2_poincare_disk(self): points = self.H2.random_uniform(self.n_samples) visualization.plot(points, space='H2_poincare_disk') @geomstats.tests.np_only def test_plot_points_h2_poincare_half_plane(self): points = self.H2.random_uniform(self.n_samples) visualization.plot(points, space='H2_poincare_half_plane') @geomstats.tests.np_only def test_plot_points_h2_klein_disk(self): points = self.H2.random_uniform(self.n_samples) visualization.plot(points, space='H2_klein_disk')
def __init__(self, n_disks, point_type='ball'): self.n_disks = n_disks self.point_type = point_type disk = Hyperbolic(dimension=2, point_type=point_type) list_disks = [disk, ] * n_disks super(PoincarePolydisk, self).__init__( manifolds=list_disks) self.metric = PoincarePolydiskMetric(n_disks=n_disks, point_type=point_type)
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 __init__(self, n_disks, coords_type='ball'): self.n_disks = n_disks self.coords_type = coords_type self.point_type = PoincarePolydisk.default_point_type disk = Hyperbolic(dimension=2, coords_type=coords_type) list_disks = [disk, ] * n_disks super(PoincarePolydisk, self).__init__( manifolds=list_disks, default_point_type='matrix') self.metric = PoincarePolydiskMetric(n_disks=n_disks, coords_type=coords_type)
def test_extrinsic_half_plane_extrinsic(self): x_in = gs.array([0.5, 7]) x = self.intrinsic_manifold.to_coordinates(x_in, to_coords_type='extrinsic') x_up = self.extrinsic_manifold.to_coordinates( x, to_coords_type='half-plane') x2 = Hyperbolic.change_coordinates_system(x_up, 'half-plane', 'extrinsic') self.assertAllClose(x, x2, atol=1e-8)
def test_product_distance_extrinsic_representation(self): """Test the distance using the extrinsic representation.""" coords_type = 'extrinsic' point_a_intrinsic = gs.array([[0.01, 0.0]]) point_b_intrinsic = gs.array([[0.0, 0.0]]) hyperbolic_space = Hyperbolic(dimension=2, coords_type=coords_type) point_a = hyperbolic_space.from_coordinates(point_a_intrinsic, "intrinsic") point_b = hyperbolic_space.from_coordinates(point_b_intrinsic, "intrinsic") duplicate_point_a = gs.vstack([point_a, point_a]) duplicate_point_b = gs.vstack([point_b, point_b]) single_disk = PoincarePolydisk(n_disks=1, coords_type=coords_type) two_disks = PoincarePolydisk(n_disks=2, coords_type=coords_type) distance_single_disk = single_disk.metric.dist(point_a, point_b) distance_two_disks = two_disks.metric.dist(duplicate_point_a, duplicate_point_b) result = distance_two_disks expected = 3**0.5 * distance_single_disk self.assertAllClose(result, expected)
def test_inner_product_matrix_matrix(self): space = ProductManifold(manifolds=[ Hypersphere(dimension=2).embedding_manifold, Hyperbolic(dimension=2).embedding_manifold ], default_point_type='matrix') point = space.random_uniform(1) result = space.metric.inner_product_matrix(point) expected = gs.identity(6) expected[3, 3] = -1 self.assertAllClose(result, expected)
def kmean_poincare_ball(): n_samples = 20 dim = 2 n_clusters = 2 manifold = Hyperbolic(dimension=dim, point_type='ball') 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(riemannian_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
def intrinsic_to_extrinsic_coords(self, point_intrinsic): """Convert point from intrinsic to extrensic coordinates. Convert the parameterization of a point in the hyperbolic space from its intrinsic coordinates, to its extrinsic coordinates in Minkowski space. Parameters ---------- point_intrinsic : array-like, shape=[n_samples, n_disk, dimension] Returns ------- point_extrinsic : array-like, shape=[n_samples, n_disks, dimension + 1] """ n_disks = point_intrinsic.shape[1] hyperbolic_space = Hyperbolic(dimension=2) point_extrinsic = gs.stack( [hyperbolic_space.from_coordinates( point_intrinsic[:, i_disk, ...], 'intrinsic') for i_disk in range(n_disks)], axis=1) return point_extrinsic
def test_product_distance_extrinsic_representation(self): point_type = 'extrinsic' point_a_intrinsic = gs.array([0.01, 0.0]) point_b_intrinsic = gs.array([0.0, 0.0]) hyperbolic_space = Hyperbolic(dimension=2, point_type=point_type) point_a = hyperbolic_space.intrinsic_to_extrinsic_coords( point_a_intrinsic) point_b = hyperbolic_space.intrinsic_to_extrinsic_coords( point_b_intrinsic) duplicate_point_a = gs.zeros((2, ) + point_a.shape) duplicate_point_a[0] = point_a duplicate_point_a[1] = point_a duplicate_point_b = gs.zeros((2, ) + point_b.shape) duplicate_point_b[0] = point_b duplicate_point_b[1] = point_b single_disk = PoincarePolydisk(n_disks=1, point_type=point_type) two_disks = PoincarePolydisk(n_disks=2, point_type=point_type) distance_single_disk = single_disk.metric.dist(point_a, point_b) distance_two_disks = two_disks.metric.dist(duplicate_point_a, duplicate_point_b) result = distance_two_disks expected = 3**0.5 * distance_single_disk self.assertAllClose(result, expected)
def setUp(self): gs.random.seed(1234) self.dimension = 2 self.extrinsic_manifold = Hyperbolic(dimension=self.dimension) self.ball_manifold = Hyperbolic(dimension=self.dimension, point_type='ball') self.intrinsic_manifold = Hyperbolic(dimension=self.dimension, point_type='intrinsic') self.half_plane_manifold = Hyperbolic(dimension=self.dimension, point_type='half-plane') self.ball_metric = HyperbolicMetric(dimension=self.dimension, point_type='ball') self.extrinsic_metric = HyperbolicMetric(dimension=self.dimension, point_type='extrinsic') self.n_samples = 10
def intrinsic_to_extrinsic_coords(self, point_intrinsic): """Convert from intrinsic to extrinsic coordinates. Parameters ---------- point_intrinsic : array-like, shape=[..., dim] Point in the embedded manifold in intrinsic coordinates. """ if self.dim != point_intrinsic.shape[-1]: raise NameError("Wrong intrinsic dimension: " + str(point_intrinsic.shape[-1]) + " instead of " + str(self.dim)) return\ Hyperbolic.change_coordinates_system(point_intrinsic, 'intrinsic', 'extrinsic')
def extrinsic_to_intrinsic_coords(self, point_extrinsic): """Convert from extrinsic to intrinsic coordinates. Parameters ---------- point_extrinsic : array-like, shape=[..., dim_embedding] Point in the embedded manifold in extrinsic coordinates, i. e. in the coordinates of the embedding manifold. """ belong_point = self.belongs(point_extrinsic) if not gs.all(belong_point): raise NameError("Point do not belong to the hyperboloid") return\ Hyperbolic.change_coordinates_system(point_extrinsic, 'extrinsic', 'intrinsic')
def empirical_frechet_var_bubble(n_samples, theta, dim, n_expectation=1000): """Variance of the empirical Fréchet mean for a bubble distribution. Draw n_sampless from a bubble distribution, computes its empirical Fréchet mean and the square distance to the asymptotic mean. This is repeated n_expectation times to compute an approximation of its expectation (i.e. its variance) by sampling. The bubble distribution is an isotropic distributions on a Riemannian hyper sub-sphere of radius 0 < theta = around the north pole of the hyperbolic space of dimension dim. Parameters ---------- n_samples: number of samples to draw theta: radius of the bubble distribution dim: dimension of the hyperbolic space (embedded in R^{1,dim}) n_expectation: number of computations for approximating the expectation Returns ------- tuple (variance, std-dev on the computed variance) """ assert dim > 1, "Dim > 1 needed to draw a uniform sample on sub-sphere" var = [] hyperbole = Hyperbolic(dimension=dim) bubble = Hypersphere(dimension=dim - 1) origin = gs.zeros(dim + 1) origin[0] = 1.0 for k in range(n_expectation): # Sample n points from the uniform distribution on a sub-sphere # of radius theta (i.e cos(theta) in ambient space) data = gs.zeros((n_samples, dim + 1), dtype=gs.float64) directions = bubble.random_uniform(n_samples) for i in range(n_samples): for j in range(dim): data[i, j + 1] = gs.sinh(theta) * directions[i, j] data[i, 0] = gs.cosh(theta) current_mean = _adaptive_gradient_descent(data, metric=hyperbole.metric, n_max_iterations=64, init_points=[origin]) var.append(hyperbole.metric.squared_dist(origin, current_mean)) return np.mean(var), 2 * np.std(var) / np.sqrt(n_expectation)
def intrinsic_to_extrinsic_coords(self, point_intrinsic): """Convert point from intrinsic to extrensic coordinates. Convert the parameterization of a point on the Hyperbolic space from its intrinsic coordinates, to its extrinsic coordinates in Minkowski space. Parameters ---------- point_intrinsic : array-like, shape=[n_diskx, n_samples, dimension] Returns ------- point_extrinsic : array-like, shape=[n_disks, n_samples, dimension + 1] """ n_disks = point_intrinsic.shape[0] return gs.array([Hyperbolic._intrinsic_to_extrinsic_coordinates( point_intrinsic[i_disks, ...]) for i_disks in range(n_disks)])