Skip to content

Commit

Permalink
Add the Student's t RandomVariable
Browse files Browse the repository at this point in the history
  • Loading branch information
rlouf authored and brandonwillard committed Nov 3, 2022
1 parent 1a3ec8d commit eadc6e3
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
55 changes: 55 additions & 0 deletions aesara/tensor/random/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,60 @@ def rng_fn_scipy(cls, rng, b, loc, scale, size):
truncexpon = TruncExponentialRV()


class StudentTRV(ScipyRandomVariable):
r"""A Student's t continuous random variable.
The probability density function for `t` in terms of its degrees of freedom
parameter :math:`\nu`, location parameter :math:`\mu` and scale
parameter :math:`\sigma` is:
.. math::
f(x; \nu, \alpha, \beta) = \frac{\Gamma(\frac{\nu + 1}{2})}{\Gamma(\frac{\nu}{2})} \left(\frac{1}{\pi\nu\sigma}\right)^{\frac{1}{2}} \left[1+\frac{(x-\mu)^2}{\nu\sigma}\right]^{-\frac{\nu+1}{2}}
for :math:`\nu > 0`, :math:`\sigma > 0`.
"""
name = "t"
ndim_supp = 0
ndims_params = [0, 0, 0]
dtype = "floatX"
_print_name = ("StudentT", "\\operatorname{StudentT}")

def __call__(self, df, loc=0.0, scale=1.0, size=None, **kwargs):
r"""Draw samples from a Student's t distribution.
Signature
---------
`(), (), () -> ()`
Parameters
----------
df
Degrees of freedom parameter :math:`\nu` of the distribution. Must be
positive.
loc
Location parameter :math:`\mu` of the distribution.
scale
Scale parameter :math:`\sigma` of the distribution. Must be
positive.
size
Sample shape. If the given size is `(m, n, k)`, then `m * n * k`
independent, identically distributed samples are returned. Default is
`None` in which case a single sample is returned.
"""
return super().__call__(df, loc, scale, size=size, **kwargs)

@classmethod
def rng_fn_scipy(cls, rng, df, loc, scale, size):
return stats.t.rvs(df, loc=loc, scale=scale, size=size, random_state=rng)


t = StudentTRV()


class BernoulliRV(ScipyRandomVariable):
r"""A Bernoulli discrete random variable.
Expand Down Expand Up @@ -2071,4 +2125,5 @@ def __call__(self, x, **kwargs):
"standard_normal",
"negative_binomial",
"gengamma",
"t",
]
3 changes: 3 additions & 0 deletions doc/library/tensor/random/basic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ Aesara can produce :class:`RandomVariable`\s that draw samples from many differe
.. autoclass:: aesara.tensor.random.basic.StandardNormalRV
:members: __call__

.. autoclass:: aesara.tensor.random.basic.StudentTRV
:members: __call__

.. autoclass:: aesara.tensor.random.basic.TriangularRV
:members: __call__

Expand Down
43 changes: 43 additions & 0 deletions tests/tensor/random/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
poisson,
randint,
standard_normal,
t,
triangular,
truncexpon,
uniform,
Expand Down Expand Up @@ -926,6 +927,48 @@ def test_truncexpon_samples(b, loc, scale, size):
)


@pytest.mark.parametrize(
"df, loc, scale, size",
[
(
np.array(2, dtype=config.floatX),
np.array(0, dtype=config.floatX),
np.array(1, dtype=config.floatX),
None,
),
(
np.array(2, dtype=config.floatX),
np.array(0, dtype=config.floatX),
np.array(1, dtype=config.floatX),
[],
),
(
np.array(2, dtype=config.floatX),
np.array(0, dtype=config.floatX),
np.array(1, dtype=config.floatX),
[2, 3],
),
(
np.full((1, 2), 5, dtype=config.floatX),
np.array(0, dtype=config.floatX),
np.array(1, dtype=config.floatX),
None,
),
],
)
def test_t_samples(df, loc, scale, size):
compare_sample_values(
t,
df,
loc,
scale,
size=size,
test_fn=lambda *args, size=None, random_state=None, **kwargs: t.rng_fn(
random_state, *(args + (size,))
),
)


@pytest.mark.parametrize(
"p, size",
[
Expand Down

0 comments on commit eadc6e3

Please sign in to comment.