Exemplo n.º 1
0
    def __init__(
        self,
        metric,
        max_iter=32,
        epsilon=EPSILON,
        point_type=None,
        method="default",
        lr=1.0,
        verbose=False,
    ):

        self.metric = metric
        self.max_iter = max_iter
        self.epsilon = epsilon
        self.point_type = point_type
        self.method = method
        self.lr = lr
        self.verbose = verbose
        self.estimate_ = None

        if point_type is None:
            self.point_type = metric.default_point_type
        error.check_parameter_accepted_values(
            self.point_type, "point_type", ["vector", "matrix"]
        )
Exemplo n.º 2
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)
Exemplo n.º 3
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)
Exemplo n.º 4
0
    def fit(self, X, y=None, weights=None):
        """Compute the empirical Frechet mean.

        Parameters
        ----------
        X : {array-like, sparse matrix}, shape=[..., n_features]
            Training input samples.
        y : array-like, shape=[...,] or [..., n_outputs]
            Target values (class labels in classification, real numbers in
            regression).
            Ignored.
        weights : array-like, shape=[...,]
            Weights associated to the points.
            Optional, default: None.

        Returns
        -------
        self : object
            Returns self.
        """
        is_linear_metric = isinstance(
            self.metric, (EuclideanMetric, MatricesMetric, MinkowskiMetric))

        error.check_parameter_accepted_values(
            self.method, 'method',
            ['default', 'adaptive', 'frechet-poincare-ball'])

        if is_linear_metric:
            mean = linear_mean(
                points=X, weights=weights, point_type=self.point_type)

        elif self.method == 'default':
            mean = _default_gradient_descent(
                points=X, weights=weights, metric=self.metric,
                max_iter=self.max_iter, initial_step_size=self.lr,
                point_type=self.point_type, epsilon=self.epsilon,
                verbose=self.verbose)
        elif self.method == 'adaptive':
            mean = _adaptive_gradient_descent(
                points=X, weights=weights, metric=self.metric,
                max_iter=self.max_iter, point_type=self.point_type,
                epsilon=self.epsilon, verbose=self.verbose,
                initial_tau=self.lr)
        elif self.method == 'frechet-poincare-ball':
            mean = _ball_gradient_descent(
                points=X, weights=weights, metric=self.metric,
                lr=self.lr, tau=self.epsilon, max_iter=self.max_iter)

        self.estimate_ = mean

        return self
Exemplo n.º 5
0
    def tangent_translation_map(self,
                                point,
                                left_or_right="left",
                                inverse=False):
        r"""Compute the push-forward map by the left/right translation.

        Compute the push-forward map, of the left/right translation by the
        point. It corresponds to the tangent map, or differential of the
        group multiplication by the point or its inverse. For groups with a
        vector representation, it is only implemented at identity, but it can
        be used at other points by passing `inverse=True`. This method wraps
        the jacobian translation which actually computes the matrix
        representation of the map.

        Parameters
        ----------
        point : array-like, shape=[..., {dim, [n, n]]
            Point.
        left_or_right : str, {'left', 'right'}
            Whether to calculate the differential of left or right
            translations.
            Optional, default: 'left'
        inverse : bool,
            Whether to inverse the jacobian matrix. If True, the push forward
            by the translation by the inverse of point is returned.
            Optional, default: False.

        Returns
        -------
        tangent_map : callable
            Tangent map of the left/right translation by point. It can be
            applied to tangent vectors.
        """
        errors.check_parameter_accepted_values(left_or_right, "left_or_right",
                                               ["left", "right"])
        if self.default_point_type == "matrix":
            if inverse:
                point = self.inverse(point)
            if left_or_right == "left":
                return lambda tangent_vec: Matrices.mul(point, tangent_vec)
            return lambda tangent_vec: Matrices.mul(tangent_vec, point)

        jacobian = self.jacobian_translation(point, left_or_right)
        if inverse:
            jacobian = gs.linalg.inv(jacobian)
        return lambda tangent_vec: gs.einsum("...ij,...j->...i", jacobian,
                                             tangent_vec)
Exemplo n.º 6
0
def integrate(function, initial_state, end_time=1.0, n_steps=10, step='euler'):
    """Compute the flow under the vector field using symplectic euler.

    Integration function to compute flows of vector fields
    on a regular grid between 0 and a finite time from an initial state.

    Parameters
    ----------
    function : callable
        Vector field to integrate.
    initial_state : tuple of arrays
        Initial position and speed.
    end_time : float
        Final integration time.
        Optional, default : 1.
    n_steps : int
        Number of integration steps to use.
        Optional, default : 10.
    step : str, {'euler', 'rk4', 'group_rk2', 'group_rk4'}
        Numerical scheme to use for elementary integration steps.
        Optional, default : 'euler'.

    Returns
    -------
    final_state : tuple
        sequences of solutions every end_time / n_steps. The shape of each
        element of the sequence is the same as the vectors passed in
        initial_state.
    """
    check_parameter_accepted_values(step, 'step', STEP_FUNCTIONS)

    dt = end_time / n_steps
    positions = [initial_state[0]]
    velocities = [initial_state[1]]
    current_state = (positions[0], velocities[0])

    step_function = globals()[STEP_FUNCTIONS[step]]

    for _ in range(n_steps):
        current_state = step_function(state=current_state,
                                      force=function,
                                      dt=dt)
        positions.append(current_state[0])
        velocities.append(current_state[1])
    return positions, velocities
Exemplo n.º 7
0
    def __init__(self,
                 metric,
                 max_iter=32,
                 epsilon=EPSILON,
                 point_type=None,
                 method='default',
                 verbose=False):

        self.metric = metric
        self.max_iter = max_iter
        self.epsilon = epsilon
        self.point_type = point_type
        self.method = method
        self.verbose = verbose
        self.estimate_ = None

        if point_type is None:
            self.point_type = metric.default_point_type
        error.check_parameter_accepted_values(self.point_type, 'point_type',
                                              ['vector', 'matrix'])
Exemplo n.º 8
0
    def fit(self, X, y=None, weights=None):
        """Compute the empirical Frechet mean.

        Parameters
        ----------
        X : {array-like, sparse matrix}, shape=[..., {dim, [n, n]}]
            Training input samples.
        y : array-like, shape=[...,] or [..., n_outputs]
            Target values (class labels in classification, real numbers in
            regression).
            Ignored.
        weights : array-like, shape=[...,]
            Weights associated to the points.
            Optional, default: None.

        Returns
        -------
        self : object
            Returns self.
        """
        metric_str = self.metric.__str__()
        is_linear_metric = (
            "EuclideanMetric" in metric_str
            or "MatricesMetric" in metric_str
            or "MinkowskiMetric" in metric_str
        )

        if "HypersphereMetric" in metric_str and self.metric.dim == 1:
            mean = Hypersphere.angle_to_extrinsic(_circle_mean(X))

        error.check_parameter_accepted_values(
            self.method, "method", ["default", "adaptive", "batch"]
        )

        if is_linear_metric:
            mean = linear_mean(points=X, weights=weights, point_type=self.point_type)

        elif self.method == "default":
            mean = _default_gradient_descent(
                points=X,
                weights=weights,
                metric=self.metric,
                max_iter=self.max_iter,
                initial_step_size=self.lr,
                point_type=self.point_type,
                epsilon=self.epsilon,
                verbose=self.verbose,
            )
        elif self.method == "adaptive":
            mean = _adaptive_gradient_descent(
                points=X,
                weights=weights,
                metric=self.metric,
                max_iter=self.max_iter,
                point_type=self.point_type,
                epsilon=self.epsilon,
                verbose=self.verbose,
                initial_tau=self.lr,
            )
        elif self.method == "batch":
            mean = _batch_gradient_descent(
                points=X,
                weights=weights,
                metric=self.metric,
                lr=self.lr,
                epsilon=self.epsilon,
                max_iter=self.max_iter,
                point_type=self.point_type,
                verbose=self.verbose,
            )

        self.estimate_ = mean

        return self