arianna-ppl


Namearianna-ppl JSON
Version 0.1.22 PyPI version JSON
download
home_pageNone
SummaryArianna probabilistic programming language
upload_time2025-01-22 16:31:56
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
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"
}
        
Elapsed time: 0.79831s