Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get the transform docs into the API pages. #3690

Merged
merged 12 commits into from
Nov 26, 2019
1 change: 1 addition & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ API Reference
api/data
api/model
api/model_graph
api/variables
api/shape_utils


Expand Down
1 change: 1 addition & 0 deletions docs/source/api/distributions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ Distributions
distributions/multivariate
distributions/mixture
distributions/timeseries
distributions/transforms
distributions/utilities
138 changes: 138 additions & 0 deletions docs/source/api/distributions/transforms.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
****************************************************************
Transformations of a random variable from one space to another.
****************************************************************

Note that for convenience these entities can be addressed as
``pm.transforms.``\ *X* for any name *X*, although they are actually
implemented as ``pm.distributions.transforms.``\*X*.

.. currentmodule:: pymc3.distributions.transforms
.. autosummary::

transform
stick_breaking
logodds
interval
log_exp_m1
lowerbound
upperbound
ordered
log
sum_to_1
t_stick_breaking
circular
CholeskyCovPacked
Chain



Transform Instances
~~~~~~~~~~~~~~~~~~~

Transform instances are the entities that should be used in the
``transform`` parameter to a random variable constructor. These are
initialized instances of the Transform Classes, which are described
below.

.. glossary::
``stick_breaking``
Instantiation of :class:`~pymc3.distributions.transforms.StickBreaking`
:class:`~pymc3.distributions.transforms.Transform` class for use in the ``transform``
argument of a random variable.

``logodds``
Instantiation of
:class:`~pymc3.distributions.transforms.LogOdds` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.

``interval``
Alias of
:class:`~pymc3.distributions.transforms.Interval` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.

``log_exp_m1``
Instantiation of
:class:`~pymc3.distributions.transforms.LogExpM1` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.

``lowerbound``
Alias of
:class:`~pymc3.distributions.transforms.LowerBound` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.

``upperbound``
Alias of
:class:`~pymc3.distributions.transforms.UpperBound` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.

``ordered``
Instantiation of
:class:`~pymc3.distributions.transforms.Ordered` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.

``log``
Instantiation of
:class:`~pymc3.distributions.transforms.Log` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.


``sum_to_1``
Instantiation of
:class:`~pymc3.distributions.transforms.SumTo1` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.


``circular``
Instantiation of
:class:`~pymc3.distributions.transforms.Circular` :class:`~pymc3.distributions.transforms.Transform` class
for use in the ``transform`` argument of a random variable.


.. autofunction:: t_stick_breaking


Transform Base Classes
~~~~~~~~~~~~~~~~~~~~~~

Typically the programmer will not use these directly.

.. autoclass:: Transform
:members:
.. autoclass:: transform
:members:
.. autoclass:: TransformedDistribution
:members:


Transform Composition Classes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. autoclass:: Chain
:members:
.. autoclass:: CholeskyCovPacked
:members:


Specific Transform Classes
~~~~~~~~~~~~~~~~~~~~~~~~~~

.. autoclass:: Log
:members:
.. autoclass:: LogExpM1
:members:
.. autoclass:: LogOdds
:members:
.. autoclass:: Interval
:members:
.. autoclass:: LowerBound
:members:
.. autoclass:: UpperBound
:members:
.. autoclass:: Ordered
:members:
.. autoclass:: SumTo1
:members:
.. autoclass:: StickBreaking
:members:
.. autoclass:: Circular
:members:
28 changes: 28 additions & 0 deletions docs/source/api/variables.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Random Variables
----------------

.. currentmodule:: pymc3.model

The normal PyMC3 programmer will typically not need to interact with these classes, except possibly when debugging. Otherwise they are primarily of interest to developers.


.. autoclass:: PyMC3Variable
:members:


.. autoclass:: ValueGradFunction
:members:


.. autoclass:: FreeRV
:members:

.. autoclass:: ObservedRV
:members:

.. autoclass:: MultiObservedRV
:members:

.. autoclass:: TransformedRV
:members:

14 changes: 8 additions & 6 deletions docs/source/developer_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -378,25 +378,27 @@ https://github.com/pymc-devs/pymc3/blob/6d07591962a6c135640a3c31903eba66b34e71d8
self.add_random_variable(var)
return var

In general, if there is observed, the RV is defined as a ``ObservedRV``,
otherwise if it has a transformed method, it is a ``TransformedRV``, otherwise, it returns the
most elementary form: a ``FreeRV``.
In general, if a variable has observations (``observed`` parameter), the RV is defined as an ``ObservedRV``,
otherwise if it has a ``transformed`` (``transform`` parameter) attribute, it is a
``TransformedRV``, otherwise, it will be the most elementary form: a
``FreeRV``. Note that this means that random variables with
observations cannot be transformed.

Below, I will take a deeper look into ``TransformedRV``, a normal user
Below, I will take a deeper look into ``TransformedRV``. A normal user
might not necessary come in contact with the concept, as
``TransformedRV`` and ``TransformedDistribution`` are intentionally not
user facing.

Because in PyMC3 there is no bijector class like in TFP or pyro, we only
have a partial implementation called ``Transform``, which implements
Jacobian correction for forward mapping only (there is no Jacobian
correction for inverse mapping). The use case we considered are limited
correction for inverse mapping). The uses case we considered are limited
rpgoldman marked this conversation as resolved.
Show resolved Hide resolved
to the set of distributions that are bounded, and the transformation
maps the bounded set to the real line - see
`doc <https://docs.pymc.io/notebooks/api_quickstart.html#Automatic-transforms-of-bounded-RVs>`__.
In general, PyMC3 does not provide explicit functionality to transform
one distribution to another. Instead, a dedicated distribution is
usually created in consideration of optimising performance. But getting a
usually created in order to optimise performance. But getting a
``TransformedDistribution`` is also possible (see also in
`doc <https://docs.pymc.io/notebooks/api_quickstart.html#Transformed-distributions-and-changes-of-variables>`__):

Expand Down
1 change: 1 addition & 0 deletions pymc3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from .blocking import *
from .distributions import *
from .distributions import transforms
from .glm import *
from . import gp
from .math import logaddexp, logsumexp, logit, invlogit, expand_packed_triangular, probit, invprobit
Expand Down
6 changes: 0 additions & 6 deletions pymc3/distributions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@
from .timeseries import MvGaussianRandomWalk
from .timeseries import MvStudentTRandomWalk

from .transforms import transform
from .transforms import stick_breaking
from .transforms import logodds
from .transforms import log
from .transforms import sum_to_1

from .bound import Bound

__all__ = ['Uniform',
Expand Down
22 changes: 20 additions & 2 deletions pymc3/distributions/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@


__all__ = [
"Transform",
"transform",
"stick_breaking",
"logodds",
Expand All @@ -23,6 +24,9 @@
"log",
"sum_to_1",
"t_stick_breaking",
"circular",
"CholeskyCovPacked",
"Chain",
]


Expand Down Expand Up @@ -231,6 +235,7 @@ def jacobian_det(self, x):
log_exp_m1 = LogExpM1()



class LogOdds(ElemwiseTransform):
name = "logodds"

Expand All @@ -250,6 +255,7 @@ def forward_val(self, x, point=None):
logodds = LogOdds()



class Interval(ElemwiseTransform):
"""Transform from real line interval [a,b] to whole real line."""

Expand Down Expand Up @@ -325,6 +331,10 @@ def jacobian_det(self, x):


lowerbound = LowerBound
'''
Alias for ``LowerBound`` (:class: LowerBound) Transform (:class: Transform) class
for use in the ``transform`` argument of a random variable.
'''


class UpperBound(ElemwiseTransform):
Expand Down Expand Up @@ -362,6 +372,11 @@ def jacobian_det(self, x):


upperbound = UpperBound
'''
Alias for ``UpperBound`` (:class: UpperBound) Transform (:class: Transform) class
for use in the ``transform`` argument of a random variable.
'''



class Ordered(Transform):
Expand Down Expand Up @@ -396,6 +411,10 @@ def jacobian_det(self, y):


ordered = Ordered()
'''
Instantiation of ``Ordered`` (:class: Ordered) Transform (:class: Transform) class
for use in the ``transform`` argument of a random variable.
'''


class SumTo1(Transform):
Expand Down Expand Up @@ -506,6 +525,7 @@ def jacobian_det(self, y_):
stick_breaking = StickBreaking()



def t_stick_breaking(eps):
return StickBreaking(eps)

Expand Down Expand Up @@ -534,7 +554,6 @@ def jacobian_det(self, x):

circular = Circular()


class CholeskyCovPacked(Transform):
name = "cholesky-cov-packed"

Expand All @@ -558,7 +577,6 @@ def forward_val(self, y, point=None):
def jacobian_det(self, y):
return tt.sum(y[self.diag_idxs])


class Chain(Transform):
def __init__(self, transform_list):
self.transform_list = transform_list
Expand Down