{ "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 0, "cells": [ { "cell_type": "markdown", "source": [ "# Reasoning about Joint Probability Distributions\n", "\n", "This tutorial walks through the inference capabilities of\n", "`jpt.trees.JPT`.\n", "We cover every supported query type:\n", "\n", "| Query | Method | Returns |\n", "|---|---|---|\n", "| Marginal $P(\\mathcal{E}=e)$ | `infer` | `float` |\n", "| Conditional $P(Q \\mid E)$ | `infer` | `float` |\n", "| Posterior distributions $P(Q \\mid E)$ | `posterior` | `VariableMap` of distributions |\n", "| Expected values $\\mathbb{E}[Q \\mid E]$ | `expectation` | `VariableMap` of scalars |\n", "| Most probable explanation (MPE) | `mpe` | assignment + likelihood |\n", "| $k$ most probable explanations | `kmpe` | iterator of assignments |\n", "\n", "We first train a model on the Iris dataset (the same setup as in\n", "[tutorial_learning](tutorial_learning.ipynb))." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "import sklearn.datasets\n", "import pandas as pd\n", "from jpt.variables import infer_from_dataframe\n", "from jpt.trees import JPT\n", "\n", "dataset = sklearn.datasets.load_iris()\n", "df = pd.DataFrame(columns=dataset.feature_names, data=dataset.data)\n", "\n", "target = dataset.target.astype(object)\n", "for idx, name in enumerate(dataset.target_names):\n", " target[target == idx] = name\n", "\n", "df['plant'] = target\n", "\n", "variables = infer_from_dataframe(df)\n", "varnames = {v.name: v for v in variables}\n", "\n", "model = JPT(variables, min_samples_leaf=0.1)\n", "model.fit(df)\n", "model" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:25:04.577690296Z", "start_time": "2026-03-16T20:25:03.196171831Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 1 }, { "cell_type": "markdown", "source": [ "## Marginal Queries\n", "\n", "A **marginal query** computes the probability of a partial state\n", "$P(\\mathcal{E} = e)$ by integrating out all unassigned variables. In\n", "``pyjpt`` this is expressed as a call to\n", "`infer` with a `query`\n", "but no `evidence`.\n", "\n", "The query is a plain Python `dict` mapping variable names (or variable\n", "objects) to values or ranges. Ranges for numeric variables are given as\n", "two-element lists `[lower, upper]`." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "# P(plant = 'setosa')\n", "p_setosa = model.infer(query={'plant': 'setosa'})\n", "print(f'P(plant=setosa) = {p_setosa:.4f}')\n", "\n", "# P(sepal length in [5, 6])\n", "p_sepal = model.infer(query={'sepal length (cm)': [5., 6.]})\n", "print(f'P(sepal length in [5,6]) = {p_sepal:.4f}')\n", "\n", "# Joint marginal: P(plant in {setosa, versicolor} AND sepal length in [5, 6])\n", "p_joint = model.infer(\n", " query={\n", " 'plant': {'setosa', 'versicolor'},\n", " 'sepal length (cm)': [5., 6.]\n", " }\n", ")\n", "print(f'P(plant in {{setosa,versicolor}}, sepal in [5,6]) = {p_joint:.4f}')" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:25:19.125431844Z", "start_time": "2026-03-16T20:25:19.077985585Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "P(plant=setosa) = 0.3333\n", "P(sepal length in [5,6]) = 0.3861\n", "P(plant in {setosa,versicolor}, sepal in [5,6]) = 0.3310\n" ] } ], "execution_count": 2 }, { "cell_type": "markdown", "source": [ "## Conditional Queries\n", "\n", "A **conditional query** computes $P(Q \\mid E) = P(Q, E) / P(E)$. The\n", "`query` argument specifies $Q$ and the `evidence` argument specifies $E$.\n", "The method returns a scalar probability." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "# P(plant = 'virginica' | sepal length in [6, 7])\n", "p_cond = model.infer(\n", " query={'plant': 'virginica'},\n", " evidence={'sepal length (cm)': [6., 7.]}\n", ")\n", "print(f'P(plant=virginica | sepal in [6,7]) = {p_cond:.4f}')\n", "\n", "# P(petal length > 4 | plant = 'versicolor')\n", "p_petal = model.infer(\n", " query={'petal length (cm)': [4., float('inf')]},\n", " evidence={'plant': 'versicolor'}\n", ")\n", "print(f'P(petal length > 4 | plant=versicolor) = {p_petal:.4f}')" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:26:16.210661411Z", "start_time": "2026-03-16T20:26:16.156185170Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "P(plant=virginica | sepal in [6,7]) = 0.5918\n", "P(petal length > 4 | plant=versicolor) = 0.6864\n" ] } ], "execution_count": 3 }, { "cell_type": "markdown", "source": [ "When the evidence has zero probability (unsatisfiable), `infer` raises an\n", "exception by default. Pass `fail_on_unsatisfiability=False` to get `None`\n", "instead:" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "result = model.infer(\n", " query={'plant': 'setosa'},\n", " evidence={'plant': 'virginica'},\n", " fail_on_unsatisfiability=False\n", ")\n", "print('Result for contradictory evidence:', result)" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:26:20.280584995Z", "start_time": "2026-03-16T20:26:20.220200943Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Result for contradictory evidence: 0.0\n" ] } ], "execution_count": 4 }, { "cell_type": "markdown", "source": [ "## Posterior Distributions\n", "\n", "While `infer` collapses the answer to a single number,\n", "`posterior` returns\n", "the full posterior distribution over each query variable given the evidence.\n", "The result is a\n", "`VariableMap`\n", "mapping each variable to its posterior distribution object.\n", "\n", "For **numeric variables** the posterior is a\n", "`Numeric` distribution; its `pdf`\n", "and `cdf` attributes are callable functions over the real line.\n", "\n", "For **symbolic variables** the posterior is a\n", "`Multinomial` distribution; its\n", "`probabilities` array is indexed in the same order as `variable.domain`." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "post = model.posterior(\n", " variables=[varnames['petal length (cm)'], varnames['plant']],\n", " evidence={'sepal length (cm)': [5.5, 6.5]}\n", ")\n", "\n", "# --- Numeric posterior: plot the PDF ---\n", "petal_dist = post[varnames['petal length (cm)']]\n", "x = np.linspace(0.5, 7.5, 300)\n", "y = [petal_dist.pdf(xi) for xi in x]\n", "\n", "plt.figure()\n", "plt.plot(x, y)\n", "plt.xlabel('petal length (cm)')\n", "plt.ylabel('density')\n", "plt.title('Posterior PDF of petal length | sepal length in [5.5, 6.5]')\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "# --- Symbolic posterior: bar chart ---\n", "plant_dist = post[varnames['plant']]\n", "labels = list(varnames['plant'].domain)\n", "probs = [plant_dist.p(label) for label in labels]\n", "\n", "plt.figure()\n", "plt.bar(labels, probs)\n", "plt.ylabel('probability')\n", "plt.title('Posterior P(plant | sepal length in [5.5, 6.5])')\n", "plt.tight_layout()\n", "plt.show()" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:26:26.530151478Z", "start_time": "2026-03-16T20:26:26.124838640Z" } }, "outputs": [ { "data": { "text/plain": [ "
" ], "image/png": "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" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } }, { "ename": "TypeError", "evalue": "'type' object is not iterable", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 24\u001b[39m\n\u001b[32m 22\u001b[39m \u001b[38;5;66;03m# --- Symbolic posterior: bar chart ---\u001b[39;00m\n\u001b[32m 23\u001b[39m plant_dist = post[varnames[\u001b[33m'\u001b[39m\u001b[33mplant\u001b[39m\u001b[33m'\u001b[39m]]\n\u001b[32m---> \u001b[39m\u001b[32m24\u001b[39m labels = \u001b[38;5;28;43mlist\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mvarnames\u001b[49m\u001b[43m[\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43mplant\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m.\u001b[49m\u001b[43mdomain\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 25\u001b[39m probs = [plant_dist.p(label) \u001b[38;5;28;01mfor\u001b[39;00m label \u001b[38;5;129;01min\u001b[39;00m labels]\n\u001b[32m 27\u001b[39m plt.figure()\n", "\u001b[31mTypeError\u001b[39m: 'type' object is not iterable" ] } ], "execution_count": 5 }, { "cell_type": "markdown", "source": [ "Note that the posterior variables are returned **independently**: the\n", "`VariableMap` does not encode the joint distribution over the query\n", "variables, only the marginal of each. If you need the full conditional joint\n", "distribution, use\n", "`conditional_jpt`." ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "## Expectations\n", "\n", "`expectation`\n", "computes $\\mathbb{E}[Q_i \\mid E]$ for each variable in a query set and\n", "returns a `VariableMap` of scalar values.\n", "\n", "For symbolic variables the expectation is not defined; those variables are\n", "silently skipped." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "numeric_vars = [\n", " varnames['sepal width (cm)'],\n", " varnames['petal length (cm)'],\n", " varnames['petal width (cm)']\n", "]\n", "\n", "exp = model.expectation(\n", " variables=numeric_vars,\n", " evidence={'plant': 'versicolor'}\n", ")\n", "\n", "for var, value in exp.items():\n", " print(f'E[{var.name} | plant=versicolor] = {value:.4f}')" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:26:47.117328229Z", "start_time": "2026-03-16T20:26:47.057059262Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "E[sepal width (cm) | plant=versicolor] = 2.7411\n", "E[petal length (cm) | plant=versicolor] = 4.1313\n", "E[petal width (cm) | plant=versicolor] = nan\n" ] } ], "execution_count": 6 }, { "cell_type": "markdown", "source": [ "## Most Probable Explanation (MPE)\n", "\n", "The **most probable explanation** query answers\n", "$\\operatorname{argmax}_{Q} P(Q \\mid E)$: given evidence $E$, find the\n", "assignment of unobserved variables that jointly maximises the probability.\n", "\n", "`mpe` returns a tuple of\n", "`(assignments, likelihood)`. `assignments` is a list of\n", "`LabelAssignment`\n", "objects \u2014 multiple assignments may be returned when several leaves tie for\n", "the maximum. The `likelihood` is the joint probability density/mass of the\n", "best assignment." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "assignments, likelihood = model.mpe(\n", " evidence={'plant': 'virginica'}\n", ")\n", "\n", "print(f'Likelihood of best explanation: {likelihood:.6f}')\n", "for i, assignment in enumerate(assignments):\n", " print(f' Assignment {i}: {assignment}')" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:26:59.836392482Z", "start_time": "2026-03-16T20:26:59.764839703Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Likelihood of best explanation: 7.072741\n", " Assignment 0: , sepal width (cm): , petal length (cm): , petal width (cm): , plant: {np.str_('virginica')}}>\n" ] } ], "execution_count": 7 }, { "cell_type": "markdown", "source": [ "## k Most Probable Explanations (k-MPE)\n", "\n", "`kmpe` generalises MPE\n", "to return an iterator that yields the $k$ best explanations in descending\n", "order of likelihood. This is useful when the single best assignment is not\n", "sufficient, e.g. to present a ranked list of hypotheses.\n", "\n", "Set `k=0` to retrieve all explanations (bounded by the number of leaves)." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "k = 3\n", "\n", "print(f'Top-{k} explanations given plant=versicolor:\\n')\n", "for rank, (assignment, likelihood) in enumerate(\n", " model.kmpe(evidence={'plant': 'versicolor'}, k=k),\n", " start=1\n", "):\n", " print(f' Rank {rank} (likelihood={likelihood:.6f})')\n", " print(f' {assignment}\\n')" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2026-03-16T20:27:29.428235799Z", "start_time": "2026-03-16T20:27:29.363019928Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Top-3 explanations given plant=versicolor:\n", "\n", " Rank 1 (likelihood=4.204493)\n", " , petal length (cm): , sepal width (cm): , sepal length (cm): }>\n", "\n", " Rank 2 (likelihood=3.822266)\n", " , petal length (cm): , sepal width (cm): , sepal length (cm): }>\n", "\n", " Rank 3 (likelihood=3.503744)\n", " , petal length (cm): , sepal width (cm): , sepal length (cm): }>\n", "\n" ] } ], "execution_count": 8 }, { "cell_type": "markdown", "source": [ "## Using `bind` to Construct Queries\n", "\n", "All inference methods accept raw Python `dict` objects, but\n", "`bind` can be used to\n", "construct a validated\n", "`LabelAssignment`\n", "explicitly. This is useful for reusing and inspecting queries, or when\n", "building queries programmatically.\n", "\n", "See `important_datastructures` for a full\n", "treatment of `LabelAssignment` and the underlying set types." ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "query = model.bind({\n", " 'plant': {'setosa', 'versicolor'},\n", " 'sepal length (cm)': [5., 6.]\n", "})\n", "evidence = model.bind({'petal width (cm)': [0., 1.]})\n", "\n", "print('Query: ', query)\n", "print('Evidence:', evidence)\n", "\n", "p = model.infer(query=query, evidence=evidence)\n", "print(f'\\nP(query | evidence) = {p:.4f}')" ], "metadata": { "collapsed": false }, "outputs": [], "execution_count": null } ] }