{ "cells": [ { "cell_type": "markdown", "id": "ges_quickstart-0", "metadata": { "cell_marker": "\"\"\"" }, "source": "# GES quickstart\n\n[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Abel-ai-lab/andrey/blob/main/examples/ges_quickstart.ipynb) {download}`Download this notebook <../../../examples/ges_quickstart.ipynb>`\n\nGreedy Equivalence Search (GES) recovers the CPDAG of the Markov-equivalence class from\nobservational linear-Gaussian data. We generate a three-node chain and recover its structure." }, { "cell_type": "markdown", "id": "7fb27b941602401d91542211134fc71a", "metadata": {}, "source": [ "## Start\n", "\n", "Choose a CPU runtime and run this cell first. In Colab it installs `andrey-core==0.9.0` from PyPI;\n", "local kernels use the installed environment." ] }, { "cell_type": "code", "execution_count": 1, "id": "acae54e37e7d407bbb7b55eff062a284", "metadata": { "tags": [ "colab-setup" ] }, "outputs": [], "source": [ "import os\n", "import sys\n", "\n", "IN_COLAB = \"google.colab\" in sys.modules\n", "\n", "if IN_COLAB:\n", " os.environ[\"ANDREY_DEVICE\"] = \"cpu\"\n", " !pip install --quiet \"andrey-core[viz]==0.9.0\" pandas" ] }, { "cell_type": "code", "execution_count": 2, "id": "ges_quickstart-1", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "\n", "import andrey" ] }, { "cell_type": "markdown", "id": "ges_quickstart-2", "metadata": {}, "source": [ "A linear-Gaussian structural equation model -- a chain `x0 -> x1 -> x2`. The columns come in an\n", "order drawn from the seed, so their order says nothing about the causal order; `shuffle=False`\n", "keeps `x0, x1, x2`." ] }, { "cell_type": "code", "execution_count": 3, "id": "ges_quickstart-3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "columns: ['x0', 'x2', 'x1']\n" ] } ], "source": [ "CHAIN = [(\"x0\", \"x1\"), (\"x1\", \"x2\")] # the true edges, cause first\n", "\n", "\n", "def sample(seed: int, n: int = 1500, shuffle: bool = True) -> pd.DataFrame:\n", " \"\"\"Draw n rows of the chain, its columns in an order drawn from the seed.\"\"\"\n", " rng = np.random.default_rng(seed)\n", " x0 = rng.standard_normal(n)\n", " x1 = 0.9 * x0 + rng.standard_normal(n)\n", " x2 = 0.9 * x1 + rng.standard_normal(n)\n", " frame = pd.DataFrame({\"x0\": x0, \"x1\": x1, \"x2\": x2})\n", " return frame[rng.permutation(frame.columns)] if shuffle else frame\n", "\n", "\n", "data = sample(seed=0)\n", "print(\"columns:\", list(data.columns))" ] }, { "cell_type": "markdown", "id": "ges_quickstart-4", "metadata": {}, "source": [ "Fit GES and inspect the recovered CPDAG (endpoint-mark adjacency) and its BIC score. The chain is\n", "Markov-equivalent to its undirected skeleton, so the CPDAG leaves the two edges unoriented." ] }, { "cell_type": "code", "execution_count": 4, "id": "ges_quickstart-5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "kind: cpdag\n", "CPDAG adjacency, in column order:\n", "[[0 0 1]\n", " [0 0 1]\n", " [1 1 0]]\n", "edges: [('x0', 'x1', 'undirected'), ('x2', 'x1', 'undirected')]\n", "BIC score: 1.0951\n" ] } ], "source": [ "out = andrey.ges(data)\n", "print(\"kind:\", out.structure.kind)\n", "print(\"CPDAG adjacency, in column order:\")\n", "print(out.structure.to_numpy())\n", "print(\"edges:\", out.structure.oriented_edges())\n", "print(\"BIC score:\", round(out.metadata[\"score\"], 4))" ] }, { "cell_type": "code", "execution_count": 5, "id": "ges_quickstart-6", "metadata": {}, "outputs": [ { "data": { "text/html": [ "x0x2x1" ], "text/plain": [ "'x0x2x1'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import andrey.viz\n", "\n", "andrey.viz.draw(out.structure)" ] }, { "cell_type": "markdown", "id": "ges_quickstart-7", "metadata": {}, "source": [] } ], "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.12.12" } }, "nbformat": 4, "nbformat_minor": 5 }