phinate / clarinet

A functional implementation of probabilistic networks.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

clarinet 🎵

Binder

Actions Status codecov pre-commit.ci status

Documentation Status Code style: black

PyPI version PyPI platforms

GitHub Discussion

(another) Open-source probabilistic graphical model library. Designed to be easy to use and interoperable with an internally developed C-based package at Bain and Company, Roma. ** Note: This project is in pre-alpha, so expect the whole thing to be one sharp edge. **

functionality roadmap:

Completed:

  • basic DAG creation and manipulation via Node class
  • BayesNet class that wraps DAG logic
  • stringent runtime type-checking via pydantic
  • graph vizualisation capability
  • on-the-fly construction of junction tree
  • probability table naming and manipulation via xarray
  • exporting of network structure to lightweight json format
  • network interoperability with:
    • bnlearn-style modelstrings
    • HBNet json specification (Bain package)

To-do:

  • inference via probabilistic programming backend (e.g. numpyro)

usage:

Here's a basic look at the DAG-making functionality:

from clarinet import BayesNet


# bnlearn-style modelstring init
BayesNet.from_modelstring("[A][C][B|A][D|C][F|A:B:C][E|F]")
#> BayesNet(
#    nodes=<immutables.Map(
#        {
#            'C': Node(name='C', parents=(), children=('D', 'F')),
#            'F': Node(name='F', parents=('A', 'B', 'C'), children=('E',)),
#            'B': Node(name='B', parents=('A',), children=('F',)),
#            'D': Node(name='D', parents=('C',), children=()),
#            'A': Node(name='A', parents=(), children=('B', 'F')),
#            'E': Node(name='E', parents=('F',), children=())
#        }
#    ) at 0x16b5475c0>, modelstring=''
#)


# dict-style init
example_model_dict = {
    "raining": {
        "parents": ["cloudy"],
        "children": ["wet grass"],
        "states": ["raining", "not raining"],
    },
    "cloudy": {
        "children": ["raining"],
    },
    "wet grass": {
        "parents": ["raining"],
    },
}

net = BayesNet.from_dict(example_model_dict)
net
#> BayesNet(
#    nodes=<immutables.Map(
#        {
#            'wet grass': Node(name='wet grass', parents=('raining',), children=()),
#            'cloudy': Node(name='cloudy', parents=(), children=('raining',)),
#            'raining': DiscreteNode(name='raining', parents=('cloudy',), children=('wet grass',), prob_table=array([], dtype=float32), states=('raining', 'not raining'))
#        }
#    ) at 0x16a6b2100>, modelstring=''
#)


# index into the network by name to look at a particular node
net["raining"]
#> DiscreteNode(name='raining', parents=('cloudy',), children=('wet grass',), prob_table=array([], dtype=float32), states=('raining', 'not raining'))

# let's add some state names that we forgot!
net.convert_nodes(
    names=["wet grass", "cloudy"],
    new_node_types=[
        cn.DiscreteNode,
        cn.DiscreteNode
    ],
    new_node_kwargs=[
        dict(states=["wet", "dry"]),
        dict(states=["cloudy", "clear"]),
    ]
)
#> BayesNet(
#    nodes={
#        'wet grass': DiscreteNode(name='wet grass', parents=('raining',), children=(), prob_table=array([], dtype=float32), states=('wet', 'dry')),
#        'cloudy': DiscreteNode(name='cloudy', parents=(), children=('raining',), prob_table=array([], dtype=float32), states=('cloudy', 'clear')),
#        'raining': DiscreteNode(name='raining', parents=('cloudy',), children=('wet grass',), prob_table=array([], dtype=float32), states=('raining', 'not raining'))
#    }, modelstring=''
#)

About

A functional implementation of probabilistic networks.

License:BSD 3-Clause "New" or "Revised" License


Languages

Language:Jupyter Notebook 77.8%Language:Python 22.2%