Learning a CStree

This notebook shows how to learn a CStree from observational data using an exhaustive search procedure.

[9]:
import numpy as np
import networkx as nx

import cslearn.cstree as ct
import cslearn.stage as st
import cslearn.learning as ctl
import cslearn.scoring as sc

%load_ext autoreload
%autoreload 2
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload

Create a CStree

We first create a CStree which we know can be represented by a single DAG, shown below. We sample the stage probabilities from the Beta distribution with total pseudo counts 1.

[10]:
np.random.seed(5)
tree = ct.CStree([2] * 3, labels=["a", "b", "c"])

tree.update_stages(
    {
        0: [{"context": {0: 0}}, {"context": {0: 1}}],
        1: [{"context": {1: 0}}, {"context": {1: 1}}],
    }
)

tree.sample_stage_parameters(alpha=1.0)
tree.plot(full=True)
[10]:
../_images/source_learn_demo_5_0.svg
[11]:
true_adags = tree.to_minimal_context_agraphs()
print("Number of DAGs:", len(true_adags))
print("Context:", list(true_adags.keys())[0])
list(true_adags.values())[0]
Number of DAGs: 1
Context: None
[11]:
../_images/source_learn_demo_6_1.svg

Draw samples

We draw 10000 samples from this CStree.

[12]:
df = tree.sample(10000)

Calculate score tables

The structure learning (learning of CStree) uses pre-calculated scores. We restrict the number of variables in each context to be at most 2 and use the BDeu score with pseudo count 1. By letting poss_cvars=None, the possible context variables for a variable are unrestricted.

[13]:
score_table, context_scores, _ = sc.order_score_tables(
    df, max_cvars=2, poss_cvars=None, alpha_tot=1.0, method="BDeu"
)
Context score tables: 100%|██████████| 3/3 [00:00<00:00, 160.33it/s]
Creating #stagings tables: 100%|██████████| 3/3 [00:00<00:00, 2533.81it/s]
Order score tables: 100%|██████████| 3/3 [00:00<00:00, 2697.88it/s]

The dict score_table contains the order score tables and context_scores, the scores for every context of every variable.

Find the optimal CStree (staging of each level) of the best order

Given the optimal order, we find the optomial CStree consistent with this order.

[15]:
opttree = ctl._optimal_cstree_given_order(optord, context_scores)

We plot the tree before estimating the parameters.

[16]:
opttree.plot(full=True)
[16]:
../_images/source_learn_demo_21_0.svg

Estimate the parameters

Estimate the stage parameters using the BDeu prior with a total pseudo count per level of 1.

[20]:
opttree.estimate_stage_parameters(df, alpha_tot=1.0, method="BDeu")
opttree.plot(full=True)
[20]:
../_images/source_learn_demo_24_0.svg

Plot the minimal context DAGs

[18]:
opt_adags = opttree.to_minimal_context_agraphs()
print("Number of DAGs:", len(opt_adags))
print("Context:", list(opt_adags.keys())[0])
list(opt_adags.values())[0]
Number of DAGs: 1
Context: None
[18]:
../_images/source_learn_demo_26_1.svg

Note that this has the same CSI/CI statement as the original DAG representation.