Пример #1
0
def normalize_observation(observation):
    observation = _unit_norm(
        observation,
        axis=-1,
        eps=np.finfo(observation.dtype).tiny,
        eps_style='where',
    )
    return np.ascontiguousarray(np.swapaxes(observation, -2, -1))
Пример #2
0
    def _m_step(
        self,
        x,
        quadratic_form,
        affiliation,
        saliency,
        dirichlet_prior_concentration,
        hermitize,
        covariance_norm,
        eigenvalue_floor,
        weight_constant_axis,
    ):
        if saliency is None:
            masked_affiliation = affiliation

            if dirichlet_prior_concentration == 1:
                weight = np.mean(affiliation,
                                 axis=weight_constant_axis,
                                 keepdims=True)
            elif np.isposinf(dirichlet_prior_concentration):
                *independent, K, T = affiliation.shape[-2:]
                weight = np.broadcast_to(1 / K, [*independent, K, 1])
            else:
                assert dirichlet_prior_concentration >= 1, dirichlet_prior_concentration
                assert weight_constant_axis == (-1, ), (
                    'ToDo: implement weight_constant_axis ({}) for '
                    'dirichlet_prior_concentration ({}).').format(
                        weight_constant_axis, dirichlet_prior_concentration)
                # affiliation: ..., K, T
                tmp = np.sum(affiliation,
                             axis=weight_constant_axis,
                             keepdims=True)
                K, T = affiliation.shape[-2:]

                weight = (tmp + (dirichlet_prior_concentration - 1)) / (
                    T + (dirichlet_prior_concentration - 1) * K)
        else:
            assert dirichlet_prior_concentration == 1, dirichlet_prior_concentration
            masked_affiliation = affiliation * saliency[..., None, :]
            weight = _unit_norm(
                np.sum(masked_affiliation,
                       axis=weight_constant_axis,
                       keepdims=True),
                ord=1,
                axis=-1,
                eps=1e-10,
                eps_style='where',
            )

        cacg = ComplexAngularCentralGaussianTrainer()._fit(
            y=x[..., None, :, :],
            saliency=masked_affiliation,
            quadratic_form=quadratic_form,
            hermitize=hermitize,
            covariance_norm=covariance_norm,
            eigenvalue_floor=eigenvalue_floor,
        )
        return CACGMM(weight=weight, cacg=cacg)
Пример #3
0
def _estimate_mixture_weight_with_dirichlet_prior_concentration(
    affiliation,
    saliency=None,
    weight_constant_axis=-1,
    dirichlet_prior_concentration=1,
):
    """
    This function is a starting point for those that want to use a Dirichlet
    prior with a plug-in rule (i.e. MAP estimate instead of MMSE estimate).
    """
    affiliation = np.asarray(affiliation)

    if isinstance(weight_constant_axis, int) and \
            weight_constant_axis % affiliation.ndim - affiliation.ndim == -2:
        K = affiliation.shape[-2]
        return np.full([K, 1], 1 / K)

    if saliency is None:
        if dirichlet_prior_concentration == 1:
            weight = np.mean(affiliation,
                             axis=weight_constant_axis,
                             keepdims=True)
        elif np.isposinf(dirichlet_prior_concentration):
            *independent, K, T = affiliation.shape[-2:]
            weight = np.broadcast_to(1 / K, [*independent, K, 1])
        else:
            assert dirichlet_prior_concentration >= 1, dirichlet_prior_concentration  # noqa
            assert weight_constant_axis == (-1, ), (
                'ToDo: implement weight_constant_axis ({}) for '
                'dirichlet_prior_concentration ({}).').format(
                    weight_constant_axis, dirichlet_prior_concentration)
            # affiliation: ..., K, T
            tmp = np.sum(affiliation, axis=weight_constant_axis, keepdims=True)
            K, T = affiliation.shape[-2:]

            weight = (tmp + (dirichlet_prior_concentration - 1)) / (
                T + (dirichlet_prior_concentration - 1) * K)
    else:
        assert dirichlet_prior_concentration == 1, dirichlet_prior_concentration  # noqa
        masked_affiliation = affiliation * saliency[..., None, :]
        weight = _unit_norm(
            np.sum(masked_affiliation,
                   axis=weight_constant_axis,
                   keepdims=True),
            ord=1,
            axis=-1,
            eps=1e-10,
            eps_style='where',
        )

    return weight
Пример #4
0
    def _m_step(
        self,
        x,
        quadratic_form,
        affiliation,
        saliency,
        dirichlet_prior_concentration,
        hermitize,
        covariance_norm,
        eigenvalue_floor,
    ):
        if saliency is None:
            masked_affiliation = affiliation

            if dirichlet_prior_concentration == 1:
                weight = np.mean(affiliation, axis=-1)
            elif np.isposinf(dirichlet_prior_concentration):
                K, T = affiliation.shape[-2:]
                weight = np.broadcast_to(1 / K, affiliation.shape[:-1])
            else:
                assert dirichlet_prior_concentration >= 1, dirichlet_prior_concentration
                # affiliation: ..., K, T
                tmp = np.sum(affiliation, axis=-1)
                K, T = affiliation.shape[-2:]

                weight = (tmp + (dirichlet_prior_concentration - 1)) / (
                    T + (dirichlet_prior_concentration - 1) * K)
        else:
            assert dirichlet_prior_concentration == 1, dirichlet_prior_concentration
            masked_affiliation = affiliation * saliency[..., None, :]
            weight = _unit_norm(
                np.sum(masked_affiliation, axis=-1),
                ord=1,
                axis=-1,
                eps=1e-10,
                eps_style='where',
            )

        cacg = ComplexAngularCentralGaussianTrainer()._fit(
            y=x[..., None, :, :],
            saliency=masked_affiliation,
            quadratic_form=quadratic_form,
            hermitize=hermitize,
            covariance_norm=covariance_norm,
            eigenvalue_floor=eigenvalue_floor,
        )
        return CACGMM(weight=weight, cacg=cacg)
def normalize_observation(observation):
    """

    Attention: swap D and N dim

    The dimensions are swapped, because some calculations (e.g. covariance) do
    a reduction over the sample (time) dimension. Having the time dimension on
    the last axis improves the execution time.

    Args:
        observation: (..., N, D)

    Returns:
        normalized observation (..., D, N)
    """
    observation = _unit_norm(
        observation,
        axis=-1,
        eps=np.finfo(observation.dtype).tiny,
        eps_style='where',
    )
    return np.ascontiguousarray(np.swapaxes(observation, -2, -1))
Пример #6
0
def estimate_mixture_weight(
    affiliation,
    saliency=None,
    weight_constant_axis=-1,
):
    """
    Estimates the mixture weight of a mixture model.

    The simplest version (without saliency and prior):

        return np.mean(affiliation, axis=weight_constant_axis, keepdims=True)

    Args:
        affiliation: Shape: (..., K, T)
        saliency: Shape: (..., K, T)
        weight_constant_axis: int

    Returns:
        mixture weight with the same shape as affiliation, except for the
        weight_constant_axis that is a singleton:
            e.g. for weight_constant_axis == -1: (..., K, 1)
        When the weight_constant_axis is -2 or the positive counterpart,
        then the returned shape is always (K, 1) and the value if 1/K.

    >>> affiliation = [[0.4, 1, 0.4], [0.6, 0, 0.6]]
    >>> estimate_mixture_weight(affiliation)
    array([[0.6],
           [0.4]])
    >>> estimate_mixture_weight(affiliation, weight_constant_axis=-2)
    array([[0.5],
           [0.5]])
    >>> estimate_mixture_weight([affiliation, affiliation])
    array([[[0.6],
            [0.4]],
    <BLANKLINE>
           [[0.6],
            [0.4]]])
    >>> estimate_mixture_weight([affiliation, affiliation], weight_constant_axis=-2)
    array([[0.5],
           [0.5]])
    >>> estimate_mixture_weight([affiliation, affiliation], weight_constant_axis=-3)
    array([[[0.4, 1. , 0.4],
            [0.6, 0. , 0.6]]])

    """
    affiliation = np.asarray(affiliation)

    if isinstance(weight_constant_axis, int) and \
            weight_constant_axis % affiliation.ndim - affiliation.ndim == -2:
        K = affiliation.shape[-2]
        return np.full([K, 1], 1 / K)
    elif isinstance(weight_constant_axis, list):
        weight_constant_axis = tuple(weight_constant_axis)

    if saliency is None:
        weight = np.mean(affiliation, axis=weight_constant_axis, keepdims=True)
    else:
        masked_affiliation = affiliation * saliency[..., None, :]
        weight = _unit_norm(
            np.sum(masked_affiliation,
                   axis=weight_constant_axis,
                   keepdims=True),
            ord=1,
            axis=-2,
            eps=1e-10,
            eps_style='where',
        )

    return weight