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

Normal rvs method #16

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
395d2b0
Statistical functions module __init__ (with docs)
luk-f-a Aug 30, 2019
cb0cee7
Statistical functions doc source
luk-f-a Aug 30, 2019
a069909
normal distribution rvs method plus tests
luk-f-a Aug 30, 2019
05363f6
updated reference to keyword issue
luk-f-a Aug 30, 2019
f6ae4dc
added overload code
luk-f-a Jan 19, 2020
36a5660
Merge branch 'master' of https://github.com/numba/numba-scipy into no…
luk-f-a Jan 19, 2020
2c14b7a
refining overload, added lowering of constant
luk-f-a Jan 26, 2020
00aaf97
changed tests to reflected goal of jit transparency
luk-f-a Jan 26, 2020
deda5d4
changed location of overload registration
luk-f-a Jan 26, 2020
8fea01f
removed registration in tests
luk-f-a Jan 26, 2020
bf99016
print out to find 32bit problem in CI
luk-f-a Jan 26, 2020
c3f8e2c
print out to find 32bit problem in CI
luk-f-a Jan 26, 2020
c122b11
print out to find 32bit problem in CI
luk-f-a Jan 26, 2020
e573c47
print out to find 32bit problem in CI
luk-f-a Jan 26, 2020
c5b63b0
changing tests to avoid problems in 32bit machines
luk-f-a Jan 26, 2020
4851861
changing tests to avoid problems in 32bit machines
luk-f-a Jan 26, 2020
31bdab8
cleaning tests
luk-f-a Jan 26, 2020
f2dff41
cleaning up files
luk-f-a Jan 26, 2020
72d4ccc
adding stats documentations
luk-f-a Jan 26, 2020
e165994
adding stats documentation
luk-f-a Jan 26, 2020
d0feb35
cleaning unused code
luk-f-a Jan 26, 2020
edbca72
documentation
luk-f-a Jan 28, 2020
8f52ac8
small documentation fix
luk-f-a Jan 29, 2020
f85f065
small documentation fix
luk-f-a Jan 29, 2020
d099bdc
extended documentation
luk-f-a Jan 29, 2020
f4e1742
updated unboxing to read off python object attributes
luk-f-a Jan 29, 2020
01e366b
comment out temp code
luk-f-a Jan 29, 2020
23e5ff0
updated imports to Numba v0.49
luk-f-a Apr 24, 2020
fe6adc7
small change in test
luk-f-a Apr 24, 2020
a4e5f5e
CI needs to register overloads
luk-f-a Apr 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions docs/source/developer/extending_stats.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
Extending numba-scipy.stats
===========================

Contributions to numba-scipy stats are always welcomed! Even simple documentation
improvements are encouraged. If you have questions, don't hesitate to ask them.

The following is a description with the most common ways in which numba-scipy stats can be extended.


Internal structure
-------------------

Numba-scipy tries to follow `scipy.stats <https://docs.scipy.org/doc/scipy/reference/tutorial/stats.html/>`_ as closely as possible, to make it easier for users to understand and extend
the internal structure.

Each statistical distribution is represented by one class, for example
``numba_scipy.stats._continuous_distns.norm_gen_jit``. Following SciPy's convention (and breaking with Python's) these
classes have lowercase names. These classes can be thought of as generators or generic distributions,
since the actual distributions---those with a concrete value for their parameters---are the instances of these classes.
This is why in SciPy one uses, for example, ``stats.norm`` and not ``stats.norm_gen``. In SciPy, ``stats.norm``
is an instance of ``stats.norm_gen`` with the default value ``loc=0`` and ``scale=1`` for its parameters.


In both numba-scipy and SciPy, each of these generator classes inherits from a parent class, ``rv_continuous`` or ``rv_discrete`` for continuous and
discrete distributions respectively. In turn, these inherit from ``rv_generic``. These classes contain the public
methods of all distributions, for example

- rvs: Random Variates

- pdf: Probability Density Function

- cdf: Cumulative Distribution Function

- sf: Survival Function (1-CDF)

- ppf: Percent Point Function (Inverse of CDF)

- isf: Inverse Survival Function (Inverse of SF)

- stats: Return mean, variance, (Fisher’s) skew, or (Fisher’s) kurtosis

- moment: non-central moments of the distribution.

These public methods will then call a private method in each individual distribution class that implements the
specific calculations for each distribution.

There are three main areas in which numba-scipy stats can be extended:

- to add a new private method on an existing distribution
- to add a new public method for the base classes
- to add a new distribution.

.. note::
numba-scipy is currently in an early stage, and its internal structure---including the descriptions below---are
subject to change.

Adding a new private method
---------------------------

In this case, the public method in the base class already exists, but the distribution of interest has not implemented
it yet. If, for example, this were the existing class::

@jitclass(spec=rv_continuous_spec + [])
class norm_gen_jit(rv_continuous):
def _rvs(self, size):
return np.random.standard_normal(size)

then it could be extended with a method returning its probability density function::


@jitclass(spec=rv_continuous_spec + [])
class norm_gen_jit(rv_continuous):
def _rvs(self, size):
return np.random.standard_normal(size)
def _pdf(self, x):
# norm.pdf(x) = exp(-x**2/2)/sqrt(2*pi)
return _norm_pdf(x)



This method is, however, private and it will be called by ``pdf``, which is the public method
implemented in ``rv_continuous``.
In case ``rv_continuous`` did not have ``pdf`` already implemented, then it would be necessary to do so.

Adding a new public method
---------------------------

Continuing with our example, if ``rv_continuous`` did not implement ``pdf`` yet::

class rv_continuous(rv_generic):
def __init__(self, name=None, seed=None):
...

then it would be necessary to add it. A good starting point is to look into SciPy stats' implementation and bring
as much as possible. It is expected that it is not possible to jit all functionality from SciPy. For example,
``**kwargs`` cannot be used in a ``jitclass`` so the signature would have to be different in numba-scipy than in SciPy::

class rv_continuous(rv_generic):
def __init__(self, name=None, seed=None):
...

def pdf(self, x, *args):
...



Adding a new distribution
---------------------------
Our final example concerns the addition of a new class. In this case, a new class would have to be created in either
``_continuous_distns.py`` or ``_discrete_distns.py``. The required private methods can then be implemented for this
class::

@jitclass(spec=rv_continuous_spec + [])
class norm_gen_jit(rv_continuous):
def _rvs(self, size):
return np.random.standard_normal(size)

Additionally, we need to register the newly implemented distribution with Numba, so that it knows that it should
overload SciPy's version when working inside a jitted function. In order to do this, we look for the
``register_overloads`` function at the bottom of ``_continuous_distns.py`` or ``_discrete_distns.py``, and add a line
with the following structure::

overload_pyclass(<pyclass>, <jit_class>)

For example::

overload_pyclass(scipy_stats._continuous_distns.norm_gen, norm_gen_jit)


12 changes: 12 additions & 0 deletions docs/source/developer/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

Developer
================

The ``numba-scipy`` developer manual.

.. toctree::
:maxdepth: 2
:caption: Contents:

contributing.rst
extending_stats.rst
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ with ``numba-scipy`` perhaps start with the :doc:`User manual <user/index>`.

user/index.rst
reference/index.rst
developer/contributing.rst
developer/index.rst
release-notes.rst

.. not needed?
Expand Down
1 change: 1 addition & 0 deletions docs/source/reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ The ``numba-scipy`` reference manual.
:caption: Contents:

special.rst
stats.rst
3 changes: 3 additions & 0 deletions numba_scipy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ def _init_extension():
This entry_point is called by Numba when it initializes.
'''
from . import special
from .stats import register_overloads

register_overloads()
7 changes: 7 additions & 0 deletions numba_scipy/stats/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@


def register_overloads():
from ._continuous_distns import register_overloads as cont_reg_overloads
cont_reg_overloads()


34 changes: 34 additions & 0 deletions numba_scipy/stats/_continuous_distns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-

from ._distn_infrastructure import (get_distribution_names, rv_continuous,
rv_continuous_spec)
from .utils import overload_pyclass
import scipy.stats as scipy_stats
from numba.extending import overload

from numba.experimental import jitclass
import numpy as np


@jitclass(spec=rv_continuous_spec + [])
class norm_gen_jit(rv_continuous):
r"""A normal continuous random variable.
The location (``loc``) keyword specifies the mean.
The scale (``scale``) keyword specifies the standard deviation.
%(before_notes)s
Notes
-----
The probability density function for `norm` is:
.. math::
f(x) = \frac{\exp(-x^2/2)}{\sqrt{2\pi}}
for a real number :math:`x`.
%(after_notes)s
%(example)s
"""
def _rvs(self, size):
return np.random.standard_normal(size)


def register_overloads():
overload_pyclass(scipy_stats._continuous_distns.norm_gen, norm_gen_jit)

1 change: 1 addition & 0 deletions numba_scipy/stats/_discrete_distns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_distn_names= []
Loading