Skip to content

parameterspace.priors.categorical

Categorical (BasePrior)

Categorical prior with separate probabilities for each value.

Source code in parameterspace/priors/categorical.py
class Categorical(BasePrior):
    """Categorical prior with separate probabilities for each value."""

    @store_init_arguments
    def __init__(self, prior_values: Union[list, np.ndarray]):
        """
        Args:
            prior_values: Array containing the probabilities for each value.
        """
        super().__init__((0, 1))
        self.probabilities = np.array(prior_values)
        if not np.all(self.probabilities >= 0):
            raise ValueError("Probabilities must be non-negative!")

        self.probabilities = self.probabilities / np.sum(self.probabilities)
        self.numerical_values = (
            np.arange(len(self.probabilities), dtype=float) + 0.5
        ) / len(self.probabilities)

    def loglikelihood(self, value):
        return np.log(self.pdf(value))

    def pdf(self, value):
        """Probability given the numerical representation(s).

        The numerical representation is converted to integers and the corresponding
        prior_values are returned.
        If the value exceeds the given range of values, a ValueError is raised.

        Only finite values are converted, and the respective probability is computed.
        NaN and INF will result in a NaN. For example:
            value = [nan, inf, 0]
        will result in
            [NaN, NaN, p(0)].

        """
        value = np.atleast_1d(value)
        idx = np.isfinite(value)

        integer_value = np.around(len(self.probabilities) * value[idx] - 0.5).astype(
            int
        )
        pdf = np.full(value.shape, np.nan, dtype=float)

        try:
            pdf[idx] = self.probabilities[integer_value]
        except IndexError as e:
            raise ValueError(
                "Unknown value in the numerical representation for a "
                + "categorical parameter encountered!"
            ) from e
        return pdf.squeeze()

    def sample(self, num_samples=None, random_state=np.random):
        return random_state.choice(
            self.numerical_values, size=num_samples, replace=True, p=self.probabilities
        )

    def __repr__(self):
        return (
            f"Categorical prior for {len(self.probabilities)} values "
            + f"with p = {self.probabilities}"
        )

    def __eq__(self, other):
        return (
            super().__eq__(other)
            and (len(self.probabilities) == len(other.probabilities))
            and np.allclose(self.probabilities, other.probabilities)
        )

loglikelihood(self, value)

Compute the log PDF (up to an additive constant) of a given value.

Note

Values for the priors are always after the transformation!

Parameters:

Name Type Description Default
value

[description]

required

Returns:

Type Description

[descriptions]

Source code in parameterspace/priors/categorical.py
def loglikelihood(self, value):
    return np.log(self.pdf(value))

pdf(self, value)

Probability given the numerical representation(s).

The numerical representation is converted to integers and the corresponding prior_values are returned. If the value exceeds the given range of values, a ValueError is raised.

Only finite values are converted, and the respective probability is computed. NaN and INF will result in a NaN. For example: value = [nan, inf, 0] will result in [NaN, NaN, p(0)].

Source code in parameterspace/priors/categorical.py
def pdf(self, value):
    """Probability given the numerical representation(s).

    The numerical representation is converted to integers and the corresponding
    prior_values are returned.
    If the value exceeds the given range of values, a ValueError is raised.

    Only finite values are converted, and the respective probability is computed.
    NaN and INF will result in a NaN. For example:
        value = [nan, inf, 0]
    will result in
        [NaN, NaN, p(0)].

    """
    value = np.atleast_1d(value)
    idx = np.isfinite(value)

    integer_value = np.around(len(self.probabilities) * value[idx] - 0.5).astype(
        int
    )
    pdf = np.full(value.shape, np.nan, dtype=float)

    try:
        pdf[idx] = self.probabilities[integer_value]
    except IndexError as e:
        raise ValueError(
            "Unknown value in the numerical representation for a "
            + "categorical parameter encountered!"
        ) from e
    return pdf.squeeze()

sample(self, num_samples=None, random_state=<module 'numpy.random' from '/home/runner/.cache/pypoetry/virtualenvs/parameterspace-9AYrJA9h-py3.8/lib/python3.8/site-packages/numpy/random/__init__.py'>)

Draw random samples from the prior.

Parameters:

Name Type Description Default
num_samples

[description]

None

Returns:

Type Description

[descriptions]

Source code in parameterspace/priors/categorical.py
def sample(self, num_samples=None, random_state=np.random):
    return random_state.choice(
        self.numerical_values, size=num_samples, replace=True, p=self.probabilities
    )