예제 #1
0
    def test_mean_euclidean(self):
        point = gs.array([1., 4.])

        mean = FrechetMean(metric=self.euclidean.metric)
        points = [point, point, point]
        mean.fit(points)

        result = mean.estimate_
        expected = point

        self.assertAllClose(result, expected)

        points = gs.array([
            [1., 2.],
            [2., 3.],
            [3., 4.],
            [4., 5.]])
        weights = [1., 2., 1., 2.]

        mean = FrechetMean(metric=self.euclidean.metric)
        mean.fit(points, weights=weights)

        result = mean.estimate_
        expected = gs.array([16. / 6., 22. / 6.])

        self.assertAllClose(result, expected)
예제 #2
0
    def test_mean_minkowski(self):
        point = gs.array([2., -math.sqrt(3)])
        points = [point, point, point]

        mean = FrechetMean(metric=self.minkowski.metric)
        mean.fit(points)
        result = mean.estimate_

        expected = point

        self.assertAllClose(result, expected)

        points = gs.array([
            [1., 0.],
            [2., math.sqrt(3)],
            [3., math.sqrt(8)],
            [4., math.sqrt(24)]])
        weights = gs.array([1., 2., 1., 2.])

        mean = FrechetMean(metric=self.minkowski.metric)
        mean.fit(points, weights=weights)
        result = mean.estimate_
        result = self.minkowski.belongs(result)
        expected = gs.array(True)

        self.assertAllClose(result, expected)
예제 #3
0
    def test_single_cluster(self):
        gs.random.seed(10)

        sphere = Hypersphere(dim=2)
        metric = sphere.metric

        cluster = sphere.random_von_mises_fisher(kappa=100, n_samples=10)

        rms = riemannian_mean_shift(
            manifold=sphere,
            metric=metric,
            bandwidth=float("inf"),
            tol=1e-4,
            n_centers=1,
            max_iter=1,
        )
        rms.fit(cluster)
        center = rms.predict(cluster)

        mean = FrechetMean(metric=metric, init_step_size=1.0)
        mean.fit(cluster)

        result = center[0]
        expected = mean.estimate_

        self.assertAllClose(expected, result)
예제 #4
0
 def test_estimate_spd(self):
     point = SPDMatrices(3).random_point()
     points = gs.array([point, point])
     mean = FrechetMean(metric=SPDMetricAffine(3), point_type='matrix')
     mean.fit(X=points)
     result = mean.estimate_
     expected = point
     self.assertAllClose(expected, result)
예제 #5
0
 def test_stiefel_n_samples(self):
     space = Stiefel(3, 2)
     metric = space.metric
     point = space.random_point(2)
     mean = FrechetMean(metric, lr=0.5, verbose=True, method="default")
     mean.fit(point)
     result = space.belongs(mean.estimate_)
     self.assertTrue(result)
예제 #6
0
 def test_estimate_transform_spd(self):
     point = SPDMatrices(3).random_uniform()
     points = gs.array([point, point])
     mean = FrechetMean(metric=SPDMetricAffine(3), point_type='matrix')
     mean.fit(X=points)
     result = mean.transform(points)
     expected = gs.zeros((2, 6))
     self.assertAllClose(expected, result)
예제 #7
0
    def test_estimate_shape_metric(self):
        points = self.curves_2d.random_point(n_samples=2)

        mean = FrechetMean(metric=self.curves_2d.srv_metric)
        mean.fit(points)
        result = mean.estimate_

        self.assertAllClose(gs.shape(result), (points.shape[1:]))
예제 #8
0
    def test_estimate_and_belongs_default_gradient_descent_so_matrix(self):
        point = self.so_matrix.random_uniform(10)

        mean = FrechetMean(metric=self.so_matrix.bi_invariant_metric, method="default")
        mean.fit(point)

        result = self.so_matrix.belongs(mean.estimate_)
        expected = True
        self.assertAllClose(result, expected)
 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)
예제 #10
0
 def test_riemannian_normal_frechet_mean(self, dim):
     space = self.space(dim)
     mean = space.random_uniform()
     precision = gs.eye(space.dim) * 10
     sample = space.random_riemannian_normal(mean, precision, 30000)
     estimator = FrechetMean(space.metric, method="adaptive")
     estimator.fit(sample)
     estimate = estimator.estimate_
     self.assertAllClose(estimate, mean, atol=1e-1)
예제 #11
0
    def test_estimate_transform_sphere(self):
        point = gs.array([0., 0., 0., 0., 1.])
        points = gs.array([point, point])

        mean = FrechetMean(metric=self.sphere.metric)
        mean.fit(X=points)
        result = mean.transform(points)
        expected = gs.zeros_like(points)
        self.assertAllClose(expected, result)
예제 #12
0
    def test_estimate_and_belongs_curves_2d(self):
        points = self.curves_2d.random_point(n_samples=2)

        mean = FrechetMean(metric=self.curves_2d.srv_metric)
        mean.fit(points)

        result = self.curves_2d.belongs(mean.estimate_)
        expected = True
        self.assertAllClose(result, expected)
예제 #13
0
 def test_stiefel_two_samples(self):
     space = Stiefel(3, 2)
     metric = space.metric
     point = space.random_point(2)
     mean = FrechetMean(metric)
     mean.fit(point)
     result = mean.estimate_
     expected = metric.exp(metric.log(point[0], point[1]) / 2, point[1])
     self.assertAllClose(expected, result)
예제 #14
0
 def test_estimate_spd_two_samples(self):
     space = SPDMatrices(3)
     metric = SPDMetricAffine(3)
     point = space.random_point(2)
     mean = FrechetMean(metric)
     mean.fit(point)
     result = mean.estimate_
     expected = metric.exp(metric.log(point[0], point[1]) / 2, point[1])
     self.assertAllClose(expected, result)
예제 #15
0
    def test_mean_minkowski_shape(self):
        dim = 2
        point = gs.array([2., -math.sqrt(3)])
        points = [point, point, point]

        mean = FrechetMean(metric=self.minkowski.metric)
        mean.fit(points)
        result = mean.estimate_

        self.assertAllClose(gs.shape(result), (dim,))
예제 #16
0
    def test_estimate_and_belongs_adaptive_gradient_descent_so_matrix(self):
        point = self.so_matrix.random_uniform(10)

        mean = FrechetMean(
            metric=self.so_matrix.bi_invariant_metric, method='adaptive',
            verbose=True, lr=.5)
        mean.fit(point)

        result = self.so_matrix.belongs(mean.estimate_)
        self.assertTrue(result)
예제 #17
0
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 < Pi around the north pole of the
    sphere of dimension dim.

    Parameters
    ----------
    n_samples : int
        Number of samples to draw.
    theta: float
        Radius of the bubble distribution.
    dim : int
        Dimension of the sphere (embedded in R^{dim+1}).
    n_expectation: int, optional (defaults to 1000)
        Number of computations for approximating the expectation.

    Returns
    -------
    tuple (variance, std-dev on the computed variance)
    """
    if dim <= 1:
        raise ValueError(
            "Dim > 1 needed to draw a uniform sample on sub-sphere.")
    var = []
    sphere = Hypersphere(dim=dim)
    bubble = Hypersphere(dim=dim - 1)

    north_pole = gs.zeros(dim + 1)
    north_pole[dim] = 1.0
    for _ 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)
        # TODO (nina): Add this code as a method of hypersphere
        last_col = gs.cos(theta) * gs.ones(n_samples)
        last_col = last_col[:, None] if (n_samples > 1) else last_col

        directions = bubble.random_uniform(n_samples)
        rest_col = gs.sin(theta) * directions
        data = gs.concatenate([rest_col, last_col], axis=-1)

        estimator = FrechetMean(sphere.metric,
                                max_iter=32,
                                method="adaptive",
                                init_point=north_pole)
        estimator.fit(data)
        current_mean = estimator.estimate_
        var.append(sphere.metric.squared_dist(north_pole, current_mean))
    return gs.mean(var), 2 * gs.std(var) / gs.sqrt(n_expectation)
예제 #18
0
    def test_mean_euclidean_shape(self):
        dim = 2
        point = gs.array([1., 4.])

        mean = FrechetMean(metric=self.euclidean.metric)
        points = [point, point, point]
        mean.fit(points)

        result = mean.estimate_

        self.assertAllClose(gs.shape(result), (dim,))
예제 #19
0
    def test_estimate_hyperbolic(self):
        point = gs.array([2., 1., 1., 1.])
        points = gs.array([point, point])

        mean = FrechetMean(metric=self.hyperbolic.metric)
        mean.fit(X=points)
        expected = point

        result = mean.estimate_

        self.assertAllClose(result, expected)
예제 #20
0
    def test_estimate_adaptive_gradient_descent_sphere(self):
        point = gs.array([0., 0., 0., 0., 1.])
        points = gs.array([point, point])

        mean = FrechetMean(metric=self.sphere.metric, method='adaptive')
        mean.fit(X=points)

        result = mean.estimate_
        expected = point

        self.assertAllClose(expected, result)
예제 #21
0
    def test_estimate_default_gradient_descent_so3(self):
        points = self.so3.random_uniform(2)

        mean_vec = FrechetMean(
            metric=self.so3.bi_invariant_metric, method='default', lr=1.)
        mean_vec.fit(points)

        logs = self.so3.bi_invariant_metric.log(points, mean_vec.estimate_)
        result = gs.sum(logs, axis=0)
        expected = gs.zeros_like(points[0])
        self.assertAllClose(result, expected)
예제 #22
0
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 = FrechetMean(metric=hyperbolic_plane.metric)
    mean.fit(data)

    mean_estimate = mean.estimate_

    tpca = TangentPCA(metric=hyperbolic_plane.metric, n_components=2)
    tpca = tpca.fit(data, base_point=mean_estimate)
    tangent_projected_data = tpca.transform(data)

    geodesic_0 = hyperbolic_plane.metric.geodesic(
        initial_point=mean_estimate,
        initial_tangent_vec=tpca.components_[0])
    geodesic_1 = hyperbolic_plane.metric.geodesic(
        initial_point=mean_estimate,
        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)

    logging.info(
        'Coordinates of the Log of the first 5 data points at the mean, '
        'projected on the principal components:')
    logging.info('\n{}'.format(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_estimate, 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()
예제 #23
0
    def test_estimate_curves_2d(self):
        point = self.curves_2d.random_point(n_samples=1)
        points = gs.array([point, point])

        mean = FrechetMean(metric=self.curves_2d.srv_metric)
        mean.fit(X=points)

        result = mean.estimate_
        expected = point

        self.assertAllClose(expected, result)
예제 #24
0
    def test_estimate_shape_default_gradient_descent_sphere(self):
        dim = 5
        point_a = gs.array([1.0, 0.0, 0.0, 0.0, 0.0])
        point_b = gs.array([0.0, 1.0, 0.0, 0.0, 0.0])
        points = gs.array([point_a, point_b])

        mean = FrechetMean(metric=self.sphere.metric, method="default", verbose=True)
        mean.fit(points)
        result = mean.estimate_

        self.assertAllClose(gs.shape(result), (dim,))
예제 #25
0
 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)
예제 #26
0
    def test_estimate_and_belongs_default_gradient_descent_sphere(self):
        point_a = gs.array([1., 0., 0., 0., 0.])
        point_b = gs.array([0., 1., 0., 0., 0.])
        points = gs.array([point_a, point_b])

        mean = FrechetMean(metric=self.sphere.metric, method='default')
        mean.fit(points)

        result = self.sphere.belongs(mean.estimate_)
        expected = True
        self.assertAllClose(result, expected)
예제 #27
0
    def test_estimate_shape_adaptive_gradient_descent_sphere(self):
        dim = 5
        point_a = gs.array([1., 0., 0., 0., 0.])
        point_b = gs.array([0., 1., 0., 0., 0.])
        points = gs.array([point_a, point_b])

        mean = FrechetMean(metric=self.sphere.metric, method='adaptive')
        mean.fit(points)
        result = mean.estimate_

        self.assertAllClose(gs.shape(result), (dim,))
예제 #28
0
    def test_mean_matrices_shape(self):
        m, n = (2, 2)
        point = gs.array([[1., 4.], [2., 3.]])

        metric = MatricesMetric(m, n)
        mean = FrechetMean(metric=metric, point_type='matrix')
        points = [point, point, point]
        mean.fit(points)

        result = mean.estimate_

        self.assertAllClose(gs.shape(result), (m, n))
예제 #29
0
 def test_coincides_with_frechet_so(self):
     gs.random.seed(0)
     point = self.so.random_uniform(self.n_samples)
     estimator = ExponentialBarycenter(self.so, max_iter=40, epsilon=1e-10)
     estimator.fit(point)
     result = estimator.estimate_
     frechet_estimator = FrechetMean(self.so.bi_invariant_metric,
                                     max_iter=40,
                                     epsilon=1e-10)
     frechet_estimator.fit(point)
     expected = frechet_estimator.estimate_
     self.assertAllClose(result, expected)
예제 #30
0
    def test_estimate_and_belongs_hyperbolic(self):
        point_a = self.hyperbolic.random_point()
        point_b = self.hyperbolic.random_point()
        point_c = self.hyperbolic.random_point()
        points = gs.stack([point_a, point_b, point_c], axis=0)

        mean = FrechetMean(metric=self.hyperbolic.metric)
        mean.fit(X=points)

        result = self.hyperbolic.belongs(mean.estimate_)
        expected = True

        self.assertAllClose(result, expected)