@@ -1814,6 +1814,27 @@ def __init__(
18141814
18151815
18161816class GeometricProbs (Distribution ):
1817+ r"""A Geometric discrete random variable representing the number of failures
1818+ before the first success, parameterized by the success probability
1819+ (:attr:`probs`).
1820+
1821+ The probability mass function (PMF) is defined as:
1822+
1823+ .. math::
1824+
1825+ P(X = k; p) = p(1-p)^k
1826+
1827+ where :math:`p \in (0,1]` is the probability of success on each independent trial.
1828+ :math:`k \in \{0, 1, 2, \ldots\}` is the number of failures before first success.
1829+ Equivalently, the first success occurs on trial :math:`k+1`.
1830+
1831+ :param probs: Probability of success on each trial (:math:`p`).
1832+ :type probs: ArrayLike
1833+ :param validate_args: Whether to validate input constraints, defaults to
1834+ ``None``.
1835+ :type validate_args: bool, optional
1836+ """
1837+
18171838 arg_constraints = {"probs" : constraints .unit_interval }
18181839 support = constraints .nonnegative_integer
18191840
@@ -1824,6 +1845,21 @@ def __init__(self, probs: ArrayLike, *, validate_args: Optional[bool] = None):
18241845 )
18251846
18261847 def sample (self , key : jax .Array , sample_shape : tuple [int , ...] = ()) -> ArrayLike :
1848+ r"""Generates samples using inverse CDF method.
1849+
1850+ For a uniform random variable :math:`U \sim \mathrm{Uniform}[0, 1)`,
1851+ a Geometric sample is obtained as:
1852+
1853+ .. math::
1854+ X = \left\lfloor \frac{\log(1-U)}{\log(1-p)} \right\rfloor.
1855+
1856+ :param key: JAX PRNGKey for reproducibility.
1857+ :type key: jax.Array
1858+ :param sample_shape: The shape of the samples to be generated.
1859+ :type sample_shape: tuple[int, ...]
1860+ :return: Samples from Geometric distribution of shape ``sample_shape + batch_shape``.
1861+ :rtype: ArrayLike
1862+ """
18271863 assert is_prng_key (key )
18281864 probs = self .probs
18291865 dtype = jnp .result_type (probs )
@@ -1833,28 +1869,78 @@ def sample(self, key: jax.Array, sample_shape: tuple[int, ...] = ()) -> ArrayLik
18331869
18341870 @validate_sample
18351871 def log_prob (self , value : ArrayLike ) -> ArrayLike :
1872+ r"""Calculates the log of the probability mass function.
1873+
1874+ .. math::
1875+ \log P(X = k; p) = k\log(1-p) + \log p.
1876+
1877+ :param value: Values at which to evaluate the log density. Values must be nonnegative integers.
1878+ :type value: ArrayLike
1879+ :return: Log probability mass.
1880+ :rtype: ArrayLike
1881+ """
18361882 probs = jnp .where ((self .probs == 1 ) & (value == 0 ), 0 , self .probs )
18371883 return value * jnp .log1p (- probs ) + jnp .log (probs )
18381884
18391885 @lazy_property
18401886 def logits (self ) -> ArrayLike :
1887+ r"""Calculates the logits corresponding to the success probability.
1888+
1889+ .. math::
1890+ \ell = \log\left(\frac{p}{1-p}\right).
1891+ """
18411892 return _to_logits_bernoulli (self .probs )
18421893
18431894 @property
18441895 def mean (self ) -> ArrayLike :
1896+ r"""Calculates the mean of the Geometric distribution.
1897+
1898+ .. math::
1899+ \mathbb{E}[X] = \frac{1-p}{p}.
1900+ """
18451901 return 1.0 / self .probs - 1.0
18461902
18471903 @property
18481904 def variance (self ) -> ArrayLike :
1905+ r"""Calculates the variance of the Geometric distribution.
1906+
1907+ .. math::
1908+ \operatorname{Var}(X) = \frac{1-p}{p^2}.
1909+ """
18491910 return (1.0 / self .probs - 1.0 ) / self .probs
18501911
18511912 def entropy (self ) -> ArrayLike :
1913+ r"""Entropy of the Geometric distribution.
1914+
1915+ .. math::
1916+ H(X) = -\log p - \frac{1-p}{p}\log(1-p).
1917+
1918+ :return: Entropy of the Geometric distribution.
1919+ :rtype: ArrayLike
1920+ """
18521921 return - (1 - self .probs ) * jnp .log1p (- self .probs ) / self .probs - jnp .log (
18531922 self .probs
18541923 )
18551924
18561925
18571926class GeometricLogits (Distribution ):
1927+ r"""Geometric distribution parameterized by logits (:attr:`logits`).
1928+
1929+ .. math::
1930+ P(X = k \mid \ell) = \sigma(\ell)
1931+ \left(1-\sigma(\ell)\right)^k,
1932+ \qquad k \in \{0, 1, 2, \ldots\}.
1933+
1934+ where :math:`\ell` denote the logits parameter,
1935+ :math:`p = \sigma(\ell) = \displaystyle\frac{1}{1+\exp(-\ell)}` is the probability of success.
1936+
1937+ :param logits: Logits of success on each trial (:math:`logits`).
1938+ :type logits: ArrayLike
1939+ :param validate_args: Whether to validate input constraints, defaults to
1940+ ``None``.
1941+ :type validate_args: bool, optional
1942+ """
1943+
18581944 arg_constraints = {"logits" : constraints .real }
18591945 support = constraints .nonnegative_integer
18601946
@@ -1866,9 +1952,25 @@ def __init__(self, logits: ArrayLike, *, validate_args: Optional[bool] = None):
18661952
18671953 @lazy_property
18681954 def probs (self ) -> ArrayLike :
1955+ r"""The success probability obtained by applying the sigmoid function
1956+ to the logits.
1957+
1958+ .. math::
1959+ p = \sigma(\ell) = \frac{1}{1+\exp(-\ell)}.
1960+ """
18691961 return _to_probs_bernoulli (self .logits )
18701962
18711963 def sample (self , key : jax .Array , sample_shape : tuple [int , ...] = ()) -> ArrayLike :
1964+ r"""Generates samples using inverse CDF technique in logit space.
1965+
1966+ :param key: JAX pseudo-random number generator key.
1967+ :type key: jax.Array
1968+ :param sample_shape: Sample dimensions to prepend to the batch shape.
1969+ :type sample_shape: tuple[int, ...]
1970+ :return: Samples from the Geometric distribution of shape
1971+ ``sample_shape + batch_shape``.
1972+ :rtype: ArrayLike
1973+ """
18721974 assert is_prng_key (key )
18731975 logits = self .logits
18741976 dtype = jnp .result_type (logits )
@@ -1878,17 +1980,62 @@ def sample(self, key: jax.Array, sample_shape: tuple[int, ...] = ()) -> ArrayLik
18781980
18791981 @validate_sample
18801982 def log_prob (self , value : ArrayLike ) -> ArrayLike :
1983+ r"""Calculates the log probability mass function.
1984+
1985+ .. math::
1986+ \log P(X = k; \ell) = \ell - (k + 1) \operatorname{softplus}(\ell),
1987+
1988+ where, :math:`\operatorname{softplus}` is :func:`~jax.nn.softplus`.
1989+
1990+ :param value: Number of failures before the first success. Values must
1991+ be nonnegative integers.
1992+ :type value: ArrayLike
1993+ :return: Log probability mass.
1994+ :rtype: ArrayLike
1995+ """
18811996 return (- value - 1 ) * softplus (self .logits ) + self .logits
18821997
18831998 @property
18841999 def mean (self ) -> ArrayLike :
2000+ r"""Calculates the mean of the Geometric distribution.
2001+
2002+ .. math::
2003+ E[X] = \frac{1}{p}-1,
2004+
2005+ where :math:`p=\sigma(\ell)`.
2006+ """
18852007 return 1.0 / self .probs - 1.0
18862008
18872009 @property
18882010 def variance (self ) -> ArrayLike :
2011+ r"""Calculates the variance of the Geometric distribution.
2012+
2013+ .. math::
2014+ \operatorname{Var}(X) = \frac{1-p}{p^2},
2015+
2016+ implemented as,
2017+
2018+ .. math::
2019+ \operatorname{Var}(X) = \frac{1/p-1}{p},
2020+
2021+ where :math:`p=\sigma(\ell)`.
2022+ """
18892023 return (1.0 / self .probs - 1.0 ) / self .probs
18902024
18912025 def entropy (self ) -> ArrayLike :
2026+ r"""Calculates the entropy of the Geometric distribution.
2027+
2028+ .. math::
2029+ H(X) = -\frac{1-p}{p}\ln{q}-\ln{p},
2030+
2031+ where, :math:`\ln{p}=-\operatorname{softplus}(-\ell)`, :math:`\ln{q}=-\operatorname{softplus}(\ell)`,
2032+ and :math:`p=\operatorname{expit}(\ell)`. Implementation uses :func:`~jax.nn.softplus`
2033+ and :func:`~jax.scipy.special.expit` for :math:`\operatorname{softplus}`
2034+ and :math:`\operatorname{expit}`, respectively.
2035+
2036+ :return: Entropy of the Geometric distribution.
2037+ :rtype: ArrayLike
2038+ """
18922039 logq = - jax .nn .softplus (self .logits )
18932040 logp = - jax .nn .softplus (- self .logits )
18942041 p = jax .scipy .special .expit (self .logits )
@@ -1902,6 +2049,22 @@ def Geometric(
19022049 * ,
19032050 validate_args : Optional [bool ] = None ,
19042051) -> Union [GeometricProbs , GeometricLogits ]:
2052+ r"""Geometric distribution parameterized by either probabilities
2053+ or logits.
2054+
2055+ Exactly one of :attr:`probs` or :attr:`logits` must be specified.
2056+
2057+ :param probs: Probability of success on each independent trial (:math:`p`).
2058+ :type probs: ArrayLike, optional
2059+ :param logits: Logits of success on each independent trial.
2060+ :type logits: ArrayLike, optional
2061+ :param validate_args: Whether to validate input constraints, defaults to
2062+ ``None``.
2063+ :type validate_args: bool, optional
2064+ :return: A probability- or logit-parameterized Geometric distribution.
2065+ :rtype: Union[GeometricProbs, GeometricLogits]
2066+ :raises ValueError: If both or neither of :attr:`probs` and :attr:`logits` are specified.
2067+ """
19052068 assert_one_of (probs = probs , logits = logits )
19062069 if probs is not None :
19072070 return GeometricProbs (probs , validate_args = validate_args )
0 commit comments