Name | arianna-ppl JSON |
Version |
0.1.22
JSON |
| download |
home_page | None |
Summary | Arianna probabilistic programming language |
upload_time | 2025-01-22 16:31:56 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | None |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Arianna
[![CI Status][ci-status-img]](https://github.com/lanl/arianna-ppl/actions)
[![PyPI Version][pypi-version]](https://pypi.org/project/arianna-ppl/)
[![PyPI Downloads][pypi-downloads]](https://pypistats.org/packages/arianna-ppl)
A probabilistic programming language for python built on `numpy`.
## Installation
To install from PyPI (recommended):
**pip**
```
pip install arianna-ppl
```
**uv**
```
uv add arianna-ppl
```
To install the absolute latest version from `main`:
**pip**
```
pip install git+https://github.com/lanl/arianna-ppl.git
```
**uv**
```
uv add git+https://github.com/lanl/arianna-ppl.git
```
## Usage
**Model Specification (linear regression)**
```python
from typing import Optional
import numpy as np
from numpy.random import default_rng
from arianna.distributions import Gamma, Normal
from arianna.ppl.context import Context, Predictive
from arianna.ppl.inference import (
AIES,
AffineInvariantMCMC,
Chain,
LaplaceApproximation,
ParallelAIES,
RandomWalkMetropolis,
)
# Type annotation are, of course, optional. Provided only for clarity.
def linear_regression(
ctx: Context,
X: np.ndarray,
y: Optional[np.ndarray]=None,
bias: bool=True
) -> None:
_, p = X.shape
beta = ctx.rv("beta", Normal(np.zeros(p), 10))
sigma = ctx.rv("sigma", Gamma(1, 1))
mu = ctx.cached("mu", X @ beta)
if bias:
alpha = ctx.rv("alpha", Normal(0, 10))
mu += alpha
ctx.rv("y", Normal(mu, sigma), obs=y)
```
**Simulate data from Prior Predictive**
```python
nobs = 100
rng = np.random.default_rng(0)
# Generate random predictors (X).
X = rng.normal(0, 1, (nobs, 1))
# Simulate from prior predictive using Predictive.
sim_truth = Predictive.run(
linear_regression, # supplied model here.
state=dict(sigma=0.7),
rng=rng,
X=X,
# since y is None, the returned dictionary will contain y sampled from it's
# predictive distributions.
y=None,
# Not return cached values, so the sim_truth will contain only parameters
# and y.
return_cached=False,
)
# pop y so that sim_truth contains only model parameters.
y = sim_truth.pop("y")
# Now sim_truth is a dict containing ("beta", "sigma", "alpha").
```
**Affine invariant ensemble sampler**
```python
aies = AIES(
linear_regression, # model function.
nwalkers=10, # number of walkers.
# Whether or not to transform parameters into unconstrained space.
transform=True, # Set to true when possible.
# Random number generator for reproducibility.
rng=default_rng(0),
# Provide data.
X=X, y=y,
)
# Does 3000 steps, with 10 walkers, after burning for 3000, and thins by 1. At
# the end, 3000 = 3000*10 samples will be aggregated from all 10 walkers. Then,
# by default, these samples are passed into an importance sampler to reweight
# the samples, yielding 3000 samples.
chain = aies.fit(nsteps=3000, burn=3000, thin=1)
```
`chain` is an object that contains posterior samples (states).
You can iterate over `chain`.
```python
for state in chain:
print(state) # state is a e.g., dict(alpha=1.3, beta=2.5, sigma=0.6, mu=some_long_array)
break # just print the first one.
```
You can convert `chain` into a large dict with `bundle = chain.bundle`,
which is a `dict[str, ndarray]`.
You can also get the samples directly with `chain.samples`.
**Parallel Affine invariant ensemble sampler**
Works only in python 3.13t. But 3.13t does not yet work with `jupyter`.
```python
from concurrent.futures import ThreadPoolExecutor
paies = ParallelAIES(
linear_regression, # model function.
ThreadPoolExecutor(4) # use 4 cores.
nwalkers=10, # number of walkers.
# Whether or not to transform parameters into unconstrained space.
transform=True, # Set to true when possible.
# Random number generator for reproducibility.
rng=default_rng(0),
# Provide data.
X=X, y=y,
)
# Same as non-parallel version, but will be faster in python 3.13t.
# Will be slightly slower than the non-parallel version in GIL enabled python
# builds, i.e. python 3.9, 3.10, 3.11, 3.12, 3.13.
chain = paies.fit(nsteps=3000, burn=3000, thin=1)
```
**Laplace Approximation**
```python
la = LaplaceApproximation(
linear_regression,
transform=True,
rng=default_rng(0),
X=X, y=y,
)
# The MAP estimate and inverse Hessian are computed via L-BFGS optimization.
# Those estimates are used to construct a MvNormal object. 3000 samples are
# drawn from that resulting MvNormal.
chain = la.fit(nsamples=3000)
```
**Posterior Predictive**
```python
rng = default_rng
xnew = np.linspace(-3, 3, 50)
Xnew = xnew.reshape(-1, 1)
ynew = Chain(
Predictive.run(
linear_regression, state=state, rng=rng, X=Xnew, y=None
)
for state in chain
).get("y")
```
See [demos](demos/).
## Threading
As of 8 Jan 2025, `jupyter` does not work with the threaded (no-gil) version of
python 3.13 (3.13t). You can install `arianna` with python 3.13 or python 3.13t
but you cannot install `jupyter` also. If you must use `jupyter`, use python
3.10, 3.11, 3.12, 3.13 (but not 3.13t).
## LANL Software Release Information
- O4856
[ci-status-img]: https://img.shields.io/github/actions/workflow/status/lanl/arianna-ppl/CI.yml?style=flat-square&label=CI
[pypi-version]: https://img.shields.io/pypi/v/arianna-ppl?style=flat-square&label=PyPI
[pypi-downloads]: https://img.shields.io/pypi/dm/arianna-ppl?style=flat-square&label=Downloads&color=blue
Raw data
{
"_id": null,
"home_page": null,
"name": "arianna-ppl",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": "Arthur Lui <alui@lanl.gov>",
"keywords": null,
"author": null,
"author_email": "Arthur Lui <alui@lanl.gov>",
"download_url": "https://files.pythonhosted.org/packages/7d/55/4d7bc2c29b78740e3b11604e6a2eab0a7ed2b8d08b26aa5eef9a0beed6dd/arianna_ppl-0.1.22.tar.gz",
"platform": null,
"description": "# Arianna\n\n[![CI Status][ci-status-img]](https://github.com/lanl/arianna-ppl/actions)\n[![PyPI Version][pypi-version]](https://pypi.org/project/arianna-ppl/)\n[![PyPI Downloads][pypi-downloads]](https://pypistats.org/packages/arianna-ppl)\n\nA probabilistic programming language for python built on `numpy`.\n\n## Installation\nTo install from PyPI (recommended):\n\n**pip**\n```\npip install arianna-ppl\n```\n\n**uv**\n```\nuv add arianna-ppl\n```\n\nTo install the absolute latest version from `main`:\n\n**pip**\n```\npip install git+https://github.com/lanl/arianna-ppl.git\n```\n\n**uv**\n```\nuv add git+https://github.com/lanl/arianna-ppl.git\n```\n\n\n## Usage\n\n**Model Specification (linear regression)**\n```python\nfrom typing import Optional\n\nimport numpy as np\nfrom numpy.random import default_rng\n\nfrom arianna.distributions import Gamma, Normal\nfrom arianna.ppl.context import Context, Predictive\nfrom arianna.ppl.inference import (\n AIES,\n AffineInvariantMCMC,\n Chain,\n LaplaceApproximation,\n ParallelAIES,\n RandomWalkMetropolis,\n)\n\n# Type annotation are, of course, optional. Provided only for clarity.\ndef linear_regression(\n ctx: Context,\n X: np.ndarray,\n y: Optional[np.ndarray]=None,\n bias: bool=True\n) -> None:\n _, p = X.shape\n beta = ctx.rv(\"beta\", Normal(np.zeros(p), 10))\n sigma = ctx.rv(\"sigma\", Gamma(1, 1))\n mu = ctx.cached(\"mu\", X @ beta)\n if bias:\n alpha = ctx.rv(\"alpha\", Normal(0, 10))\n mu += alpha\n\n ctx.rv(\"y\", Normal(mu, sigma), obs=y)\n```\n\n**Simulate data from Prior Predictive**\n```python\nnobs = 100\nrng = np.random.default_rng(0)\n\n# Generate random predictors (X).\nX = rng.normal(0, 1, (nobs, 1))\n\n# Simulate from prior predictive using Predictive.\nsim_truth = Predictive.run(\n linear_regression, # supplied model here.\n state=dict(sigma=0.7),\n rng=rng,\n X=X,\n # since y is None, the returned dictionary will contain y sampled from it's\n # predictive distributions.\n y=None,\n # Not return cached values, so the sim_truth will contain only parameters\n # and y.\n return_cached=False, \n)\n\n# pop y so that sim_truth contains only model parameters.\ny = sim_truth.pop(\"y\")\n\n# Now sim_truth is a dict containing (\"beta\", \"sigma\", \"alpha\").\n```\n\n**Affine invariant ensemble sampler**\n```python\naies = AIES(\n linear_regression, # model function.\n nwalkers=10, # number of walkers.\n # Whether or not to transform parameters into unconstrained space.\n transform=True, # Set to true when possible.\n # Random number generator for reproducibility.\n rng=default_rng(0),\n # Provide data.\n X=X, y=y,\n)\n\n# Does 3000 steps, with 10 walkers, after burning for 3000, and thins by 1. At\n# the end, 3000 = 3000*10 samples will be aggregated from all 10 walkers. Then,\n# by default, these samples are passed into an importance sampler to reweight\n# the samples, yielding 3000 samples.\nchain = aies.fit(nsteps=3000, burn=3000, thin=1)\n```\n\n`chain` is an object that contains posterior samples (states).\nYou can iterate over `chain`.\n\n```python\nfor state in chain:\n print(state) # state is a e.g., dict(alpha=1.3, beta=2.5, sigma=0.6, mu=some_long_array)\n break # just print the first one.\n```\n\nYou can convert `chain` into a large dict with `bundle = chain.bundle`,\nwhich is a `dict[str, ndarray]`.\n\nYou can also get the samples directly with `chain.samples`.\n\n**Parallel Affine invariant ensemble sampler**\nWorks only in python 3.13t. But 3.13t does not yet work with `jupyter`.\n\n```python\nfrom concurrent.futures import ThreadPoolExecutor\n\npaies = ParallelAIES(\n linear_regression, # model function.\n ThreadPoolExecutor(4) # use 4 cores.\n nwalkers=10, # number of walkers.\n # Whether or not to transform parameters into unconstrained space.\n transform=True, # Set to true when possible.\n # Random number generator for reproducibility.\n rng=default_rng(0),\n # Provide data.\n X=X, y=y,\n)\n\n# Same as non-parallel version, but will be faster in python 3.13t.\n# Will be slightly slower than the non-parallel version in GIL enabled python\n# builds, i.e. python 3.9, 3.10, 3.11, 3.12, 3.13.\nchain = paies.fit(nsteps=3000, burn=3000, thin=1)\n```\n\n**Laplace Approximation**\n```python\nla = LaplaceApproximation(\n linear_regression,\n transform=True,\n rng=default_rng(0),\n X=X, y=y,\n)\n\n# The MAP estimate and inverse Hessian are computed via L-BFGS optimization.\n# Those estimates are used to construct a MvNormal object. 3000 samples are\n# drawn from that resulting MvNormal.\nchain = la.fit(nsamples=3000)\n```\n\n**Posterior Predictive**\n```python\nrng = default_rng\nxnew = np.linspace(-3, 3, 50)\nXnew = xnew.reshape(-1, 1)\nynew = Chain(\n Predictive.run(\n linear_regression, state=state, rng=rng, X=Xnew, y=None\n )\n for state in chain\n).get(\"y\")\n```\n\nSee [demos](demos/).\n\n## Threading\nAs of 8 Jan 2025, `jupyter` does not work with the threaded (no-gil) version of\npython 3.13 (3.13t). You can install `arianna` with python 3.13 or python 3.13t\nbut you cannot install `jupyter` also. If you must use `jupyter`, use python\n3.10, 3.11, 3.12, 3.13 (but not 3.13t).\n\n## LANL Software Release Information\n- O4856\n\n[ci-status-img]: https://img.shields.io/github/actions/workflow/status/lanl/arianna-ppl/CI.yml?style=flat-square&label=CI\n[pypi-version]: https://img.shields.io/pypi/v/arianna-ppl?style=flat-square&label=PyPI\n[pypi-downloads]: https://img.shields.io/pypi/dm/arianna-ppl?style=flat-square&label=Downloads&color=blue\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Arianna probabilistic programming language",
"version": "0.1.22",
"project_urls": {
"Changelog": "https://github.com/lanl/arianna-ppl/blob/master/CHANGELOG.md",
"Documentation": "https://lanl.github.io/arianna-ppl",
"Homepage": "https://github.com/lanl/arianna-ppl",
"Issues": "https://github.com/lanl/arianna-ppl/issues",
"Repository": "https://github.com/lanl/arianna-ppl"
},
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "2e6bf6bd8b5559453a4df46ac8652536942d13d2ce1a2fdd791ce26005a239be",
"md5": "57e11e7dc3d043347345519fec1dbbd0",
"sha256": "ffa6e15ab31bb12343ee16ddb2454cb9674f4c5a16770b0ab7eb496c4f8bca55"
},
"downloads": -1,
"filename": "arianna_ppl-0.1.22-py3-none-any.whl",
"has_sig": false,
"md5_digest": "57e11e7dc3d043347345519fec1dbbd0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 18504,
"upload_time": "2025-01-22T16:31:54",
"upload_time_iso_8601": "2025-01-22T16:31:54.314512Z",
"url": "https://files.pythonhosted.org/packages/2e/6b/f6bd8b5559453a4df46ac8652536942d13d2ce1a2fdd791ce26005a239be/arianna_ppl-0.1.22-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "7d554d7bc2c29b78740e3b11604e6a2eab0a7ed2b8d08b26aa5eef9a0beed6dd",
"md5": "63a385cff854e9a65c4d4090bf94c93c",
"sha256": "ed3641e1af43a3392afa520ac21600b00975df64912009ec39b5d46004fd2042"
},
"downloads": -1,
"filename": "arianna_ppl-0.1.22.tar.gz",
"has_sig": false,
"md5_digest": "63a385cff854e9a65c4d4090bf94c93c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 18416,
"upload_time": "2025-01-22T16:31:56",
"upload_time_iso_8601": "2025-01-22T16:31:56.490026Z",
"url": "https://files.pythonhosted.org/packages/7d/55/4d7bc2c29b78740e3b11604e6a2eab0a7ed2b8d08b26aa5eef9a0beed6dd/arianna_ppl-0.1.22.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-22 16:31:56",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lanl",
"github_project": "arianna-ppl",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "arianna-ppl"
}