Пример #1
0
    def _iterate_over_manifolds(self, func, args, intrinsic=False):

        cum_index = (
            gs.cumsum(self.dims)[:-1]
            if intrinsic
            else gs.cumsum([k + 1 for k in self.dims])
        )
        arguments = {}
        float_args = {}
        for key, value in args.items():
            if not isinstance(value, float):
                arguments[key] = gs.split(value, cum_index, axis=-1)
            else:
                float_args[key] = value
        args_list = [
            {key: arguments[key][j] for key in arguments}
            for j in range(len(self.manifolds))
        ]
        pool = joblib.Parallel(n_jobs=self.n_jobs)
        out = pool(
            joblib.delayed(self._get_method)(
                self.manifolds[i], func, {**args_list[i], **float_args}
            )
            for i in range(len(self.manifolds))
        )
        return out
Пример #2
0
    def test_cumsum(self):
        result = gs.cumsum(gs.arange(10))
        expected = gs.array(([0, 1, 3, 6, 10, 15, 21, 28, 36, 45]))
        self.assertAllClose(result, expected)

        result = gs.cumsum(gs.arange(10).reshape(2, 5), axis=1)
        expected = gs.array(([[0, 1, 3, 6, 10], [5, 11, 18, 26, 35]]))
        self.assertAllClose(result, expected)
    def _iterate_over_metrics(
            self, func, args, intrinsic=False):

        cum_index = gs.cumsum(self.dims, axis=0)[:-1] if intrinsic else \
            gs.cumsum(gs.array([k + 1 for k in self.dims]), axis=0)
        arguments = {
            key: gs.split(args[key], cum_index, axis=1) for key in args.keys()}
        args_list = [{key: arguments[key][j] for key in args.keys()} for j in
                     range(self.n_metrics)]
        pool = joblib.Parallel(n_jobs=self.n_jobs, prefer='threads')
        out = pool(
            joblib.delayed(self._get_method)(
                self.metrics[i], func, args_list[i]) for i in range(
                self.n_metrics))
        return out
Пример #4
0
    def _iterate_over_manifolds(
            self, func, args, intrinsic=False):

        cum_index = gs.cumsum(self.dims)[:-1] if intrinsic else \
            gs.cumsum([k + 1 for k in self.dims])
        arguments = {key: gs.split(
            args[key], cum_index, axis=1) for key in args.keys()}
        args_list = [{key: arguments[key][j] for key in args.keys()} for j in
                     range(len(self.manifolds))]
        pool = joblib.Parallel(n_jobs=self.n_jobs)
        out = pool(
            joblib.delayed(self._get_method)(
                self.manifolds[i], func, args_list[i]) for i in range(
                len(self.manifolds)))
        return out
Пример #5
0
    def square_root_velocity_inverse(self, srv, starting_point):
        """Retrieve a curve from sqrt velocity rep and starting point.

        Parameters
        ----------
        srv :
        starting_point :

        Returns
        -------
        curve :
        """
        if not isinstance(self.ambient_metric, EuclideanMetric):
            raise AssertionError('The square root velocity inverse is only '
                                 'implemented for dicretized curves embedded '
                                 'in a Euclidean space.')
        if gs.ndim(srv) != gs.ndim(starting_point):
            starting_point = gs.transpose(gs.tile(starting_point, (1, 1, 1)),
                                          axes=(1, 0, 2))
        srv_shape = srv.shape
        srv = gs.to_ndarray(srv, to_ndim=3)
        n_curves, n_sampling_points_minus_one, n_coords = srv.shape

        srv = gs.reshape(srv,
                         (n_curves * n_sampling_points_minus_one, n_coords))
        srv_norm = self.ambient_metric.norm(srv)
        delta_points = 1 / n_sampling_points_minus_one * srv_norm * srv
        delta_points = gs.reshape(delta_points, srv_shape)
        curve = gs.concatenate((starting_point, delta_points), -2)
        curve = gs.cumsum(curve, -2)

        return curve
Пример #6
0
 def test_fit_to_target_explained_variance(self):
     X = self.spd.random_point(n_samples=5)
     target = 0.90
     tpca = TangentPCA(self.spd_metric, n_components=target)
     tpca.fit(X)
     result = gs.cumsum(tpca.explained_variance_ratio_)[-1] > target
     expected = True
     self.assertAllClose(result, expected)
Пример #7
0
    def log(self, point, base_point):
        """Compute Riemannian logarithm of a curve wrt a base curve.

        Parameters
        ----------
        point : array-like, shape=[..., n_sampling_points, ambient_dim]
            Discrete curve.
        base_point : array-like, shape=[..., n_sampling_points, ambient_dim]
            Discrete curve to use as base point.

        Returns
        -------
        log : array-like, shape=[..., n_sampling_points, ambient_dim]
            Tangent vector to a discrete curve.
        """
        if not isinstance(self.ambient_metric, EuclideanMetric):
            raise AssertionError('The logarithm map is only implemented '
                                 'for discrete curves embedded in a '
                                 'Euclidean space.')
        point = gs.to_ndarray(point, to_ndim=3)
        base_point = gs.to_ndarray(base_point, to_ndim=3)
        n_curves, n_sampling_points, n_coords = point.shape

        curve_srv = self.square_root_velocity(point)
        base_curve_srv = self.square_root_velocity(base_point)

        base_curve_velocity = (n_sampling_points - 1) * (base_point[:, 1:, :] -
                                                         base_point[:, :-1, :])
        base_curve_velocity_norm = self.pointwise_norm(base_curve_velocity,
                                                       base_point[:, :-1, :])

        inner_prod = self.pointwise_inner_product(curve_srv - base_curve_srv,
                                                  base_curve_velocity,
                                                  base_point[:, :-1, :])
        coef_1 = gs.sqrt(base_curve_velocity_norm)
        coef_2 = 1 / base_curve_velocity_norm**(3 / 2) * inner_prod

        term_1 = gs.einsum('ij,ijk->ijk', coef_1, curve_srv - base_curve_srv)
        term_2 = gs.einsum('ij,ijk->ijk', coef_2, base_curve_velocity)
        log_derivative = term_1 + term_2

        log_starting_points = self.ambient_metric.log(
            point=point[:, 0, :], base_point=base_point[:, 0, :])
        log_starting_points = gs.to_ndarray(
            log_starting_points, to_ndim=3, axis=1)

        log_cumsum = gs.hstack(
            [gs.zeros((n_curves, 1, n_coords)),
             gs.cumsum(log_derivative, -2)])
        log = log_starting_points + 1 / (n_sampling_points - 1) * log_cumsum

        return log
Пример #8
0
    def log(self, curve, base_curve):
        """Compute Riemannian logarithm of a curve wrt a base curve.

        Parameters
        ----------
        curve :
        base_curve :

        Returns
        -------
        log :
        """
        if not isinstance(self.ambient_metric, EuclideanMetric):
            raise AssertionError('The logarithm map is only implemented '
                                 'for dicretized curves embedded in a '
                                 'Euclidean space.')
        curve = gs.to_ndarray(curve, to_ndim=3)
        base_curve = gs.to_ndarray(base_curve, to_ndim=3)
        n_curves, n_sampling_points, n_coords = curve.shape

        curve_srv = self.square_root_velocity(curve)
        base_curve_srv = self.square_root_velocity(base_curve)

        base_curve_velocity = (n_sampling_points - 1) * (base_curve[:, 1:, :] -
                                                         base_curve[:, :-1, :])
        base_curve_velocity_norm = self.pointwise_norm(base_curve_velocity,
                                                       base_curve[:, :-1, :])

        inner_prod = self.pointwise_inner_product(curve_srv - base_curve_srv,
                                                  base_curve_velocity,
                                                  base_curve[:, :-1, :])
        coef_1 = gs.sqrt(base_curve_velocity_norm)
        coef_2 = 1 / base_curve_velocity_norm**(3 / 2) * inner_prod

        term_1 = gs.einsum('ij,ijk->ijk', coef_1, curve_srv - base_curve_srv)
        term_2 = gs.einsum('ij,ijk->ijk', coef_2, base_curve_velocity)
        log_derivative = term_1 + term_2

        log_starting_points = self.ambient_metric.log(
            point=curve[:, 0, :], base_point=base_curve[:, 0, :])
        log_starting_points = gs.transpose(
            gs.tile(log_starting_points, (1, 1, 1)), (1, 0, 2))

        log_cumsum = gs.hstack(
            [gs.zeros((n_curves, 1, n_coords)),
             gs.cumsum(log_derivative, -2)])
        log = log_starting_points + 1 / (n_sampling_points - 1) * log_cumsum

        return log
Пример #9
0
def _circle_variances(mean, var, n_samples, points):
    """Compute the minimizer of the variance functional.

    Parameters
    ----------
    mean : float
        Mean angle.
    var : float
        Variance of the angles.
    n_samples : int
        Number of samples.
    points : array-like, shape=[n,]
        Data set of ordered angles.

    References
    ---------
    ..[HH15]     Hotz, T. and S. F. Huckemann (2015), "Intrinsic means on the circle:
                 Uniqueness, locus and asymptotics", Annals of the Institute of
                 Statistical Mathematics 67 (1), 177–193.
                 https://arxiv.org/abs/1108.2141
    """
    means = (mean + gs.linspace(0.0, 2 * gs.pi, n_samples + 1)[:-1]) % (2 * gs.pi)
    means = gs.where(means >= gs.pi, means - 2 * gs.pi, means)
    parts = gs.array([sum(points) / n_samples if means[0] < 0 else 0])
    m_plus = means >= 0
    left_sums = gs.cumsum(points)
    right_sums = left_sums[-1] - left_sums
    i = gs.arange(n_samples, dtype=right_sums.dtype)
    j = i[1:]
    parts2 = right_sums[:-1] / (n_samples - j)
    first_term = parts2[:1]
    parts2 = gs.where(m_plus[1:], left_sums[:-1] / j, parts2)
    parts = gs.concatenate([parts, first_term, parts2[1:]])

    # Formula (6) from [HH15]_
    plus_vec = (4 * gs.pi * i / n_samples) * (gs.pi + parts - mean) - (
        2 * gs.pi * i / n_samples
    ) ** 2
    minus_vec = (4 * gs.pi * (n_samples - i) / n_samples) * (gs.pi - parts + mean) - (
        2 * gs.pi * (n_samples - i) / n_samples
    ) ** 2
    minus_vec = gs.where(m_plus, plus_vec, minus_vec)
    means = gs.transpose(gs.vstack([means, var + minus_vec]))
    return means
Пример #10
0
    def square_root_velocity_inverse(self, srv, starting_point):
        """Retrieve a curve from sqrt velocity rep and starting point.

        Parameters
        ----------
        srv : array-like, shape=[..., n_sampling_points - 1, ambient_dim]
            Square-root velocity representation of a discrete curve.
        starting_point : array-like, shape=[..., ambient_dim]
            Point of the ambient manifold to use as start of the retrieved
            curve.

        Returns
        -------
        curve : array-like, shape=[..., n_sampling_points, ambient_dim]
            Curve retrieved from its square-root velocity.
        """
        if not isinstance(self.ambient_metric, EuclideanMetric):
            raise AssertionError('The square root velocity inverse is only '
                                 'implemented for discrete curves embedded '
                                 'in a Euclidean space.')
        if gs.ndim(srv) != gs.ndim(starting_point):
            starting_point = gs.to_ndarray(
                starting_point, to_ndim=srv.ndim, axis=1)
        srv_shape = srv.shape
        srv = gs.to_ndarray(srv, to_ndim=3)
        n_curves, n_sampling_points_minus_one, n_coords = srv.shape

        srv = gs.reshape(srv,
                         (n_curves * n_sampling_points_minus_one, n_coords))
        srv_norm = self.ambient_metric.norm(srv)
        delta_points = gs.einsum(
            '...,...i->...i', 1 / n_sampling_points_minus_one * srv_norm, srv)
        delta_points = gs.reshape(delta_points, srv_shape)
        curve = gs.concatenate((starting_point, delta_points), -2)
        curve = gs.cumsum(curve, -2)

        return curve