Type at least 2 letters. Enter opens the first result, Esc closes.

    Causal Inference · Lesson 3 · Causal graphs and the do-operator

    Causal graphs: structural causal models, d-separation, confounders and colliders

    Intermediate 90 min 5 interactive figures 3 videos Colab notebook

    Before this lesson: lesson 01 (association and its five sources) and lesson 02 (potential outcomes). From probability: conditional probability and conditional independence (probability 04); the linear-Gaussian examples use covariance and correlation (probability 05 helps). Time: about 90 minutes, plus the notebook.


    Why this matters #

    • Which variables to control for. Every causal estimate from observational data (lessons 04–08) starts with the question "what do I adjust for?". The answer is a graph question: adjust so that every non-causal path is blocked and no new path is opened. "Control for everything" is wrong, and this lesson shows why.
    • Selected data. Many ML datasets are filtered by a common effect: loans exist only for approved applicants, ratings only for items a user chose to watch, hospital records only for people who came to the hospital. Filtering on a common effect creates associations that do not exist in the population (Berkson's paradox).
    • Learning graphs from data. Causal discovery algorithms (lesson 10) test conditional independences and use d-separation to rule out graphs.
    • Probabilistic models. Bayesian networks, the graphical models behind many probabilistic ML methods, use the same factorization and the same d-separation rule (Koller and Friedman, ch. 3).

    1. Predict first #

    2. The picture #

    2.1 A model you can run #

    A structural causal model (SCM) is a small program that generates the data. Each variable gets one assignment that computes it from its direct causes and from its own random noise. Here is the classic sprinkler example (Pearl 2009, ch. 1):

    season    := U_season
    sprinkler := f_sprinkler(season, U_sprinkler)
    rain      := f_rain(season, U_rain)
    wet       := f_wet(sprinkler, rain, U_wet)
    slippery  := f_slippery(wet, U_slippery)
    

    The symbol :=:= means assignment, not equality: the right side causes the left side. If we change the sprinkler by hand, wet changes, but season does not. The noises UU are independent of each other; they stand for all the small causes that the model does not name.

    The causal graph of the SCM has one node per variable and an arrow A→BA \to B when AA appears on the right side of the assignment of BB. The inputs of a node are its parents. Here the graph is Season → Sprinkler, Season → Rain, Sprinkler → Wet, Rain → Wet, Wet → Slippery.

    • An arrow claims a possible direct effect. The function may also ignore that input; then the arrow is there but does nothing.
    • A missing arrow claims no direct effect. Season → Wet is missing: the model says that the season changes how wet the street is only through the sprinkler and the rain. This is the strong part of a graph, and it is what makes the graph testable.
    • The graph must be a directed acyclic graph (DAG): following arrows you can never come back to where you started. A variable cannot be its own cause.

    2.2 Three junctions #

    Every path in a graph is made of steps through middle nodes. There are only three ways a path can pass through a middle node BB:

    Junction Drawing Example AA and CC AA and CC given BB
    chain A→B→C{A \to B \to C} smoking → tar → cancer dependent independent
    fork (common cause) A←B→C{A \leftarrow B \to C} ice cream ← heat → drownings dependent independent
    collider (common effect) A→B←C{A \to B \leftarrow C} talent → hired ← looks independent dependent

    "Given BB" means conditioning on BB: we look at units with the same value of BB (a slice of the data), put BB into a regression, or keep only units selected by BB. The first two rows feel natural. The collider row is the surprise: two independent causes become dependent once we know their common effect.

    Interactive figure: loading…

    Switch between chain, fork and collider, then press "Condition on B". The scatter shows AA against CC for 300 units from the model in the panel. When you condition, only the units in a narrow slice of BB stay bright (yellow), with their own fitted line. In the chain and the fork the slice is a round cloud (the association disappears). In the collider the full cloud is round but the slice slopes down. The panel shows the sample correlation next to the exact value.

    Why the collider works this way. Use the coin example. Before you hear anything, coin AA tells you nothing about coin CC. Now you know the bell rang (B=1B = 1): at least one coin is heads. If AA is tails, then CC must be heads. Knowing the common effect links the two causes: one cause "explains away" the other.

    2.3 Selection is conditioning #

    Keeping only some units is a way of conditioning. If the selection depends on a common effect, it creates an association between its causes. This is Berkson's paradox (Berkson 1946, with hospital patients) or collider bias.

    Interactive figure: loading…

    Move the share selected from 100% down to 5%. Each dot is a person with two independent traits. The yellow dots are selected because the sum of the traits is in the top share; the dashed magenta line is the selection threshold. The correlation in the whole sample stays near 0, but inside the selection it becomes more and more negative: about −0.47-0.47 when half are selected and about −0.71-0.71 for the top 10%. The exact value comes from the truncated normal distribution.

    Step by step, why the hired actors show a negative correlation.

    1. The studio hires people with talent + looks above a threshold.
    2. Take a hired actor with low talent. To pass the threshold, this actor needs high looks.
    3. Take a hired actor with high talent. This actor passes with any looks.
    4. So, among hired actors, low talent goes with high looks more often than high talent does: a negative correlation that does not exist in the population.
    Quick check

    A school admits students whose test score + interview score is high. In the applicant pool the two scores are independent. A researcher uses only admitted students and finds a negative correlation between the two scores. What is the best explanation?

    2.4 Paths, and when they are blocked #

    In a bigger graph, two nodes are linked by several paths. A path is a sequence of nodes where each neighbor pair is joined by an arrow, in either direction, and no node repeats. For example, in the sprinkler graph, Sprinkler ← Season → Rain is a path, and so is Sprinkler → Wet ← Rain.

    Association can flow along a path only if every middle node lets it through. Each middle node is one of the three junctions, so the table of section 2.2 decides it:

    • a chain or fork node lets association through unless we condition on it;
    • a collider node blocks unless we condition on it or on one of its descendants.

    A path is open if every middle node lets association through; otherwise it is blocked. If every path between AA and BB is blocked, they are d-separated ("d" for directional).

    Interactive figure: loading…

    Pick two nodes with "From" and "To", then click nodes to put them into the conditioning set ZZ (yellow). The panel lists every path between the two nodes and says why each one is open or blocked. Open non-causal paths are thick magenta, open directed paths are thick aqua; dashed violet nodes are unobserved. Try Sprinkler and Rain with Z={Season}Z = \{\text{Season}\}, then add Wet. Use the other graphs, or build your own with "add node" and "add edge".

    Quick check

    In the sprinkler graph, Sprinkler and Rain are d-separated given {Season}\{\text{Season}\}. You add Slippery to the conditioning set. What happens?

    3. Definitions and main results #

    3.1 Structural causal models and graphs #

    Definition (SCM). A structural causal model has

    1. endogenous variables V1,…,VkV_1, \dots, V_k (the variables we model);
    2. exogenous noises U1,…,UkU_1, \dots, U_k, jointly independent, with a distribution P(U)P(U);
    3. one structural assignment per variable, Vj:=fj(paj,Uj)V_j := f_j(\mathrm{pa}_j, U_j), where the parents paj\mathrm{pa}_j are some of the other endogenous variables.

    Its causal graph GG has an arrow from each parent to its child. We assume GG is a DAG. Then the assignments can be run in a topological order (parents before children), and the SCM defines one joint distribution P(V)P(V) (Peters, Janzing and Schölkopf 2017, def. 6.2).

    Words for families in a graph. If A→BA \to B, then AA is a parent of BB and BB is a child of AA. If there is a directed path A→⋯→BA \to \dots \to B, then AA is an ancestor of BB and BB is a descendant of AA. A directed path follows the arrows; a path may go against them.

    3.2 The Markov factorization #

    Theorem (Markov factorization). If PP comes from an SCM with DAG GG and independent noises, then

    p(v1,…,vk)=∏j=1kp(vj∣paj).p(v_1, \dots, v_k) = \prod_{j=1}^{k} p(v_j \mid \mathrm{pa}_j).

    Proof sketch.

    1. Order the variables so that parents come before children: V1,V2,…,VkV_1, V_2, \dots, V_k.
    2. The chain rule of probability always holds: p(v)=∏jp(vj∣v1,…,vj−1)p(v) = \prod_j p(v_j \mid v_1, \dots, v_{j-1}).
    3. Vj=fj(paj,Uj)V_j = f_j(\mathrm{pa}_j, U_j). The earlier variables V1,…,Vj−1V_1, \dots, V_{j-1} are functions of the noises U1,…,Uj−1U_1, \dots, U_{j-1} only, and UjU_j is independent of those noises.
    4. So, given paj\mathrm{pa}_j, the value of VjV_j depends only on UjU_j, which the other earlier variables do not affect: p(vj∣v1,…,vj−1)=p(vj∣paj)p(v_j \mid v_1, \dots, v_{j-1}) = p(v_j \mid \mathrm{pa}_j).
    5. Put this into step 2. ■\blacksquare

    An equivalent form is the local Markov property: each node is independent of its non-descendants given its parents.

    Why this matters in numbers. With five binary variables, a general joint table has 25−1=312^5 - 1 = 31 free numbers. The sprinkler factorization needs only 1+2+2+4+2=111 + 2 + 2 + 4 + 2 = 11: one conditional probability table (CPT) per node, with one row per value of its parents. The 20 numbers we save come from the independences that the missing arrows impose.

    Interactive figure: loading…

    Move the sliders, or press "Random CPTs". The joint table below the graph is recomputed from the factorization. The checks on the right test five conditional independences. The three that the graph implies stay at gap 0.000 for every choice of numbers. The other two are usually dependent. Press "Make P(sprinkler) the same in both seasons": now Sprinkler and Rain are independent without conditioning, but only because of these special numbers.

    3.3 The three junctions, proved #

    Each statement follows from the factorization in one or two lines.

    Chain A→B→CA \to B \to C. p(a,b,c)=p(a) p(b∣a) p(c∣b)p(a, b, c) = p(a)\,p(b \mid a)\,p(c \mid b). Divide by p(a,b)p(a, b): p(c∣a,b)=p(c∣b)p(c \mid a, b) = p(c \mid b). So A⊥ ⁣ ⁣ ⁣⊥C∣BA \perp\!\!\!\perp C \mid B. Without conditioning, p(c∣a)=∑bp(b∣a) p(c∣b)p(c \mid a) = \sum_b p(b \mid a)\,p(c \mid b) depends on aa in general: dependent.

    Fork A←B→CA \leftarrow B \to C. p(a,b,c)=p(b) p(a∣b) p(c∣b)p(a, b, c) = p(b)\,p(a \mid b)\,p(c \mid b). Divide by p(b)p(b): p(a,c∣b)=p(a∣b) p(c∣b)p(a, c \mid b) = p(a \mid b)\,p(c \mid b). So A⊥ ⁣ ⁣ ⁣⊥C∣BA \perp\!\!\!\perp C \mid B. Without conditioning they are dependent in general (the common cause links them).

    Collider A→B←CA \to B \leftarrow C. p(a,b,c)=p(a) p(c) p(b∣a,c)p(a, b, c) = p(a)\,p(c)\,p(b \mid a, c).

    1. Sum over bb: p(a,c)=p(a) p(c)∑bp(b∣a,c)=p(a) p(c)p(a, c) = p(a)\,p(c) \sum_b p(b \mid a, c) = p(a)\,p(c). So A⊥ ⁣ ⁣ ⁣⊥CA \perp\!\!\!\perp C.
    2. Given bb: p(a,c∣b)=p(a) p(c) p(b∣a,c)/p(b)p(a, c \mid b) = p(a)\,p(c)\,p(b \mid a, c) / p(b). The factor p(b∣a,c)p(b \mid a, c) links aa and cc, so this does not split into a function of aa times a function of cc in general.

    The collider in numbers. Take A,C∼N(0,1)A, C \sim \mathcal N(0, 1) independent and B:=A+C+UBB := A + C + U_B with UB∼N(0,1)U_B \sim \mathcal N(0, 1). Then Var⁡(B)=3\operatorname{Var}(B) = 3, Cov⁡(A,B)=Cov⁡(C,B)=1\operatorname{Cov}(A, B) = \operatorname{Cov}(C, B) = 1, Cov⁡(A,C)=0\operatorname{Cov}(A, C) = 0. The partial correlation of AA and CC given BB is

    ρAC⋅B=ρAC−ρAB ρCB(1−ρAB2)(1−ρCB2)=0−13⋅131−13=−1/32/3=−12.\rho_{AC\cdot B} = \frac{\rho_{AC} - \rho_{AB}\,\rho_{CB}}{\sqrt{(1 - \rho_{AB}^2)(1 - \rho_{CB}^2)}} = \frac{0 - \tfrac{1}{\sqrt 3}\cdot\tfrac{1}{\sqrt 3}}{1 - \tfrac13} = \frac{-1/3}{2/3} = -\frac12 .

    For Gaussian variables, zero partial correlation is the same as conditional independence. So here AA and CC are dependent given BB, with partial correlation exactly −1/2-1/2.

    A descendant of a collider. Add D:=B+UDD := B + U_D. Conditioning on DD gives partial information about BB, so it opens the path partly: here ρAC⋅D=(0−12⋅12)/(1−14)=−13\rho_{AC\cdot D} = (0 - \tfrac12\cdot\tfrac12)/(1 - \tfrac14) = -\tfrac13. Any descendant of a collider opens the path, more weakly when it is a noisier copy.

    Quick check

    AA and CC are independent standard normal variables, B:=A+C+UBB := A + C + U_B and D:=B+UDD := B + U_D, with unit-variance noises. Which is true?

    3.4 d-separation #

    Definition (blocked path; Pearl 1988). Let ZZ be a set of nodes that does not contain the two end nodes. A path between AA and BB is blocked by ZZ if it has a middle node WW such that

    1. WW is a non-collider on the path (chain →W→\to W \to or fork ←W→\leftarrow W \to) and W∈ZW \in Z; or
    2. WW is a collider on the path (→W←\to W \leftarrow), and neither WW nor any descendant of WW is in ZZ.

    A path that is not blocked is open (or active). AA and BB are d-separated by ZZ, written A⊥GB∣ZA \perp_G B \mid Z, if every path between them is blocked by ZZ. Otherwise they are d-connected.

    Note that "collider" is a property of a node on a path, not of the node alone. In A→C→D←EA \to C \to D \leftarrow E, the node CC is a non-collider, and DD is a collider. On another path, CC may be a collider.

    Algorithm for small graphs (what the builder does).

    1. List every path between AA and BB (ignore arrow directions; no node twice).
    2. For each path, walk along its middle nodes. For each one, decide: collider or not? In ZZ? Has it a descendant in ZZ?
    3. Stop at the first node that blocks (rules 1 or 2). If no node blocks, the path is open.
    4. A⊥GB∣ZA \perp_G B \mid Z if and only if no path is open.

    Section 4 runs this algorithm by hand on a five-node graph.

    A linear-time algorithm: Bayes-ball (reachability)

    Listing paths takes exponential time in large graphs. The Bayes-ball algorithm (Shachter 1998), also called the reachability algorithm (Koller and Friedman 2009, alg. 3.1), avoids it. It does a graph search over pairs (node, direction of arrival), "up" (arriving from a child) or "down" (arriving from a parent):

    • first mark every node that is in ZZ or has a descendant in ZZ (the ancestors of ZZ, including ZZ);
    • from a node Y∉ZY \notin Z reached "up", continue to its parents (up) and its children (down);
    • from a node Y∉ZY \notin Z reached "down", continue to its children (down);
    • from a node reached "down" that is marked (in ZZ or an ancestor of ZZ), continue to its parents (up): this is the open collider. The nodes reached (outside ZZ) are exactly the nodes d-connected to the start. Each (node, direction) pair is visited once, so the time is linear in the size of the graph. The builder above uses path enumeration, and we tested it against this algorithm on 200 random graphs.

    3.5 What d-separation guarantees: Markov property and faithfulness #

    Theorem (global Markov property; Verma and Pearl 1988, Lauritzen et al. 1990). If PP factorizes over GG, then

    A⊥GB∣Z⟹A⊥ ⁣ ⁣ ⁣⊥B∣Z in P.A \perp_G B \mid Z \quad\Longrightarrow\quad A \perp\!\!\!\perp B \mid Z \text{ in } P .

    So d-separation is a sound rule: every independence it reads is true in every distribution that the SCM can produce, whatever the functions and noise distributions are.

    The converse is not always true. A distribution is faithful to GG if every conditional independence in PP comes from a d-separation in GG. Two facts:

    1. For every DAG, the rule is complete: if AA and BB are d-connected given ZZ, there is some distribution that factorizes over GG in which they are dependent given ZZ (Geiger, Verma and Pearl 1990).
    2. Unfaithful distributions are rare: for linear-Gaussian and for discrete models, they need parameter values that satisfy an exact equation, a set of measure zero (Spirtes, Glymour and Scheines 2000; Meek 1995). They are rare, but not impossible: systems that are tuned to keep something constant (body temperature, a thermostat) can produce them.

    Example of an unfaithful distribution. AA causes CC directly with weight aa, and through BB with weights bb and cc: B:=bA+UBB := bA + U_B, C:=aA+cB+UCC := aA + cB + U_C. Then Cov⁡(A,C)=a+bc\operatorname{Cov}(A, C) = a + bc. If a=−bca = -bc, the two causal paths cancel and AA and CC are uncorrelated, although AA causes CC.

    Interactive figure: loading…

    Press "Cancel the paths", then change bb or cc. The scatter shows CC against AA with the fitted line (ink) and the total effect a+bca + bc (dashed aqua). When a=−bca = -bc the line is flat: the data look as if AA had no effect on CC. Given BB, the partial correlation is still a/a2+b2+1≠0a/\sqrt{a^2 + b^2 + 1} \ne 0, so the dependence comes back. Faithfulness fails only on this thin set of weights.

    Faithfulness is an assumption about the world, not a theorem. Causal discovery (lesson 10) needs it, because it reads the graph from the independences in the data.

    3.6 Confounders, mediators, colliders and backdoor paths #

    In causal questions we name two special nodes: a treatment TT and an outcome YY. The other nodes get names by their position:

    Name Picture Meaning
    confounder T←X→YT \leftarrow X \to Y a common cause of TT and YY
    mediator T→M→YT \to M \to Y a node on a directed path from TT to YY; it carries part of the effect
    collider T→C←YT \to C \leftarrow Y (or on any path) a common effect on a path
    backdoor path T←… YT \leftarrow \dots\, Y a path from TT to YY whose first edge points into TT

    A backdoor path is never causal: it leaves TT against an arrow. If a backdoor path is open, part of the association between TT and YY is not the effect of TT. This is confounding. In the next lesson, a set that blocks every backdoor path (and has no descendant of TT) lets us compute the effect.

    M-bias: a pre-treatment collider. Look at the graph T←U1→M←U2→YT \leftarrow U_1 \to M \leftarrow U_2 \to Y with U1,U2U_1, U_2 unobserved (load "M-bias" in the builder). MM is measured before TT and is correlated with both TT and YY. It looks like a confounder. But it is a collider on the backdoor path. Without MM in ZZ the path is blocked; with MM in ZZ it is open. So "adjust for every pre-treatment variable" can create bias (Greenland, Pearl and Robins 1999). How large the bias is in practice is debated (Ding and Miratrix 2015); the point is that the graph, not the time order alone, decides.

    Quick check

    In the M-bias graph T←U1→M←U2→YT \leftarrow U_1 \to M \leftarrow U_2 \to Y (with also T→YT \to Y, and U1,U2U_1, U_2 hidden), which statement about the backdoor path is correct?

    3.7 Selection bias is collider bias #

    Let S=1S = 1 mean "this unit is in my data". If SS is caused by TT and by YY (or by their causes or effects), then using only units with S=1S = 1 conditions on a collider or on its descendant. Examples:

    • Berkson's paradox. Hospital patients: two diseases that are independent in the population become associated among patients, because each disease makes admission more likely.
    • Survivor bias. Only the companies (or planes, or patients) that survived are in the data.
    • Data filtered by an earlier model. A bank observes repayment only for applicants its model approved. Approval depends on features that also predict repayment, so a model trained on approved loans learns associations of the selected population.
    • Recommender feedback. Ratings exist only for items that users chose to watch, and the choice depends on how much they expected to like the item.
    The birth-weight paradox

    Among low-birth-weight babies, babies of smoking mothers had lower infant mortality than babies of non-smoking mothers. Smoking does not protect babies. The explanation (Hernández-Díaz, Schisterman and Hernán 2006) is a collider: low birth weight is caused by smoking and by other, more dangerous problems (for example birth defects) that also raise mortality. Conditioning on low birth weight opens the path Smoking → Low weight ← Other problem → Death. Among low-weight babies, a non-smoking mother makes it more likely that the low weight came from a more dangerous cause.

    3.8 Testable implications #

    A graph implies a list of conditional independences, one for every d-separation. We can test them with data: if the data show a clear dependence where the graph says "d-separated", the graph is wrong (or the data are selected, or the sample is too small). For example, the sprinkler graph implies Sprinkler ⊥ ⁣ ⁣ ⁣⊥\perp\!\!\!\perp Rain ∣\mid Season and Slippery ⊥ ⁣ ⁣ ⁣⊥\perp\!\!\!\perp Season ∣\mid Wet, among others.

    Two warnings:

    1. Passing the tests does not prove the graph. Different graphs can imply the same independences. The chain A→B→CA \to B \to C, the reverse chain A←B←CA \leftarrow B \leftarrow C and the fork A←B→CA \leftarrow B \to C all imply only A⊥ ⁣ ⁣ ⁣⊥C∣BA \perp\!\!\!\perp C \mid B. Only the collider A→B←CA \to B \leftarrow C differs (it implies A⊥ ⁣ ⁣ ⁣⊥CA \perp\!\!\!\perp C). Graphs with the same independences form a Markov equivalence class; lesson 10 uses this.
    2. A graph with no missing arrows implies no independences, so data can never reject it. Assumptions live in the missing arrows.

    Answers to section 1. (1) CC must be heads. The bell is a collider of the two coins; once you know it rang, the coins are dependent. (2) Negative. Hiring is a collider of talent and looks; with the top 30% selected the correlation is about −0.58-0.58 (see the Berkson figure). (3) No. Season → Rain → Wet is a chain; given Rain, Season and Wet are independent. (In the full sprinkler graph the answer changes: Season → Sprinkler → Wet is a second path, and Rain does not block it.)

    4. Worked example #

    Take five variables with the graph

    A→C,B→C,C→D,B→E,E→D.A \to C, \quad B \to C, \quad C \to D, \quad B \to E, \quad E \to D .

    We ask whether AA and EE are d-separated by different sets ZZ.

    Step 1: list the paths between AA and EE. AA has one neighbor, CC. From CC we can go to BB or to DD.

    • p1p_1: A→C←B→EA \to C \leftarrow B \to E
    • p2p_2: A→C→D←EA \to C \to D \leftarrow E

    There are no other paths (AA–CC–BB–EE and AA–CC–DD–EE are the only routes without a repeated node).

    Step 2: the type of each middle node on each path.

    • On p1p_1: CC is a collider (A→C←BA \to C \leftarrow B); BB is a fork (C←B→EC \leftarrow B \to E).
    • On p2p_2: CC is a chain node (A→C→DA \to C \to D); DD is a collider (C→D←EC \to D \leftarrow E).

    The descendants are: of CC, only DD; of DD, none.

    Step 3: check each set ZZ.

    ZZ p1p_1: CC (collider), BB (fork) p2p_2: CC (chain), DD (collider) d-separated?
    {}\{\} blocked at CC (collider, no descendant in ZZ) blocked at DD (collider) yes
    {C}\{C\} CC opens, BB passes: open blocked at CC (non-collider in ZZ) no
    {D}\{D\} CC opens (its descendant D∈ZD \in Z), BB passes: open CC passes, DD opens: open no
    {B,C}\{B, C\} blocked at BB (non-collider in ZZ) blocked at CC yes
    {B,D}\{B, D\} blocked at BB CC passes, DD opens: open no
    {C,D}\{C, D\} open blocked at CC no

    Look at the rows {C}\{C\} and {B,C}\{B, C\}. Adding BB to the set closes the path that CC opened. This is the general recipe: when you must condition on a collider, also condition on a non-collider next to it on the same path.

    Step 4: check with numbers. Make the graph a linear-Gaussian SCM with all weights 1 and unit-variance noises: A:=UAA := U_A, B:=UBB := U_B, C:=A+B+UCC := A + B + U_C, E:=B+UEE := B + U_E, D:=C+E+UDD := C + E + U_D. For Gaussian variables, d-separation shows up as a partial correlation of exactly 0. The exact values, from the covariance matrix, are:

    ZZ {}\{\} {C}\{C\} {D}\{D\} {B,C}\{B, C\} {B,D}\{B, D\} {C,D}\{C, D\}
    ρAE⋅Z\rho_{AE \cdot Z} 00 −0.316-0.316 −0.429-0.429 00 −0.333-0.333 −0.200-0.200

    The zeros are exactly the d-separated rows. For one value, by hand: with Z={C}Z = \{C\}, Var⁡(C)=3\operatorname{Var}(C) = 3, Cov⁡(A,C)=1\operatorname{Cov}(A, C) = 1, Cov⁡(E,C)=1\operatorname{Cov}(E, C) = 1, Var⁡(E)=2\operatorname{Var}(E) = 2, Cov⁡(A,E)=0\operatorname{Cov}(A, E) = 0. So ρAC=1/3\rho_{AC} = 1/\sqrt 3, ρEC=1/6\rho_{EC} = 1/\sqrt 6, and

    ρAE⋅C=0−13⋅16(1−13)(1−16)=−1/185/9=−110≈−0.316.\rho_{AE\cdot C} = \frac{0 - \frac{1}{\sqrt 3}\cdot\frac{1}{\sqrt 6}}{\sqrt{\left(1 - \frac13\right)\left(1 - \frac16\right)}} = \frac{-1/\sqrt{18}}{\sqrt{5/9}} = -\frac{1}{\sqrt{10}} \approx -0.316 .

    5. In code #

    The code simulates the worked example and computes partial correlations from the precision matrix (the inverse of the covariance matrix): for the variables (a,b,Z)(a, b, Z), ρab⋅Z=−Θab/ΘaaΘbb\rho_{ab\cdot Z} = -\Theta_{ab}/\sqrt{\Theta_{aa}\Theta_{bb}} with Θ=Σ(a,b,Z)−1\Theta = \Sigma_{(a, b, Z)}^{-1}. A d-separation function by path enumeration checks the same sets.

    import numpy as np
    
    # graph: parents of each node
    parents = {"A": [], "B": [], "C": ["A", "B"], "E": ["B"], "D": ["C", "E"]}
    edges = [(p, c) for c, ps in parents.items() for p in ps]
    
    def descendants(v):
        out, stack = set(), [v]
        while stack:
            u = stack.pop()
            for p, c in edges:
                if p == u and c not in out:
                    out.add(c)
                    stack.append(c)
        return out
    
    def paths(a, b, path=None):
        path = path or [a]
        if path[-1] == b:
            yield path
            return
        for p, c in edges:
            for u, w in ((p, c), (c, p)):
                if u == path[-1] and w not in path:
                    yield from paths(a, b, path + [w])
    
    def blocked(path, Z):
        for u, v, w in zip(path, path[1:], path[2:]):
            collider = (u, v) in edges and (w, v) in edges
            if not collider and v in Z:
                return True                    # chain or fork node in Z
            if collider and v not in Z and not descendants(v) & Z:
                return True                    # collider, not opened by Z
        return False
    
    def d_separated(a, b, Z):
        return all(blocked(p, Z) for p in paths(a, b))
    
    # simulate the linear-Gaussian SCM (all weights 1)
    rng = np.random.default_rng(0)
    n = 200_000
    A = rng.normal(size=n); B = rng.normal(size=n)
    C = A + B + rng.normal(size=n)
    E = B + rng.normal(size=n)
    D = C + E + rng.normal(size=n)
    data = {"A": A, "B": B, "C": C, "D": D, "E": E}
    
    def partial_corr(a, b, Z):
        X = np.column_stack([data[v] for v in [a, b, *Z]])
        Theta = np.linalg.inv(np.cov(X.T))
        return -Theta[0, 1] / np.sqrt(Theta[0, 0] * Theta[1, 1])
    
    for Z in [set(), {"C"}, {"D"}, {"B", "C"}, {"B", "D"}, {"C", "D"}]:
        print(sorted(Z), d_separated("A", "E", Z), round(partial_corr("A", "E", sorted(Z)), 3))
    # [] True -0.002
    # ['C'] False -0.317
    # ['D'] False -0.429
    # ['B', 'C'] True -0.0
    # ['B', 'D'] False -0.334
    # ['C', 'D'] False -0.202
    

    The sample values differ from the exact ones only in the third digit. In a real analysis we would test "partial correlation = 0" with a Fisher zz-test; the notebook does this.

    6. Where it shows up #

    • Choosing controls in observational studies. Epidemiology and economics draw DAGs before they choose covariates (Hernán and Robins 2020, ch. 6–8). The backdoor criterion of the next lesson is d-separation in a modified graph.
    • Bayesian networks. Medical diagnosis networks, fault diagnosis and other probabilistic graphical models store a joint distribution as a product of CPTs and answer queries with the independences that d-separation gives. The Markov blanket of a node (parents, children and the other parents of its children) d-separates it from all other nodes, so it is the smallest sufficient feature set for predicting that node.
    • Causal discovery. The PC algorithm removes an edge between two nodes as soon as it finds a set that makes them independent, and orients colliders from the pattern of independences (lesson 10).
    • Selection bias in ML data. Loan data, click logs, filtered web text and datasets of "accepted" items are selected on a common effect. Debiasing methods (inverse propensity weighting of observed ratings, lesson 05) start from the selection graph.
    • ML for science. In particle physics, a trigger keeps only events with large total energy; this selection is on a common effect of the energies of the particles, and it creates correlations between them that the analysis must model. In clinical data, only tested patients have a test result, so analyses of "tested patients" condition on the decision to test.

    7. Common mistakes #

    • "Conditioning on more variables can only reduce bias." False. Conditioning on a collider, or on a descendant of one, opens a path that was blocked.
    • Treating "collider" as a property of a node. A node is a collider on a path. The same node can be a collider on one path and a chain node on another (node CC in section 4).
    • Following only the arrow directions. Paths in d-separation can go against the arrows; backdoor paths always start against an arrow.
    • Forgetting descendants. A collider is opened also by conditioning on any of its descendants, for example on a noisy measurement of it.
    • Reading "no arrow" as "no information". A missing arrow is the strongest claim in the graph. A missing common cause (no dashed UU) claims that there is no unmeasured confounding.
    • Believing a graph because the data pass its tests. Markov-equivalent graphs pass the same tests, and an unfaithful distribution can hide a real effect. Check: list the graphs that imply the same independences before you claim a direction.

    8. Check yourself #

    1. Write the Markov factorization of the graph X→TX \to T, X→YX \to Y, T→YT \to Y, Y→SY \to S.
      Answerp(x,t,y,s)=p(x) p(t∣x) p(y∣t,x) p(s∣y)p(x, t, y, s) = p(x)\,p(t \mid x)\,p(y \mid t, x)\,p(s \mid y): one factor per node, conditioned on its parents.
    2. In the fork A←B→CA \leftarrow B \to C, what can you say about AA and CC given BB? And in the collider A→B←CA \to B \leftarrow C?
      AnswerFork: independent given BB (conditioning on the common cause blocks the path). Collider: dependent given BB in general (conditioning on the common effect opens the path), although AA and CC are independent without conditioning.
    3. Graph: T←X→YT \leftarrow X \to Y, T→YT \to Y, T→S←YT \to S \leftarrow Y. Which paths between TT and YY are open when Z={X}Z = \{X\}? When Z={X,S}Z = \{X, S\}?
      AnswerPaths: T→YT \to Y (always open: no middle node), T←X→YT \leftarrow X \to Y, T→S←YT \to S \leftarrow Y. With Z={X}Z = \{X\}: T→YT \to Y open, the backdoor path blocked at XX, the path through SS blocked (collider not in ZZ). With Z={X,S}Z = \{X, S\}: the path through SS also opens, because SS is a collider in ZZ.
    4. Give two different graphs on A,B,CA, B, C that imply exactly the same independences, and one that implies a different one.
      AnswerA→B→CA \to B \to C and A←B→CA \leftarrow B \to C both imply only A⊥ ⁣ ⁣ ⁣⊥C∣BA \perp\!\!\!\perp C \mid B. The collider A→B←CA \to B \leftarrow C implies A⊥ ⁣ ⁣ ⁣⊥CA \perp\!\!\!\perp C (without conditioning) instead.
    5. A dataset contains only employees who are still at the company after two years. Training satisfaction and salary both make people stay. Why can satisfaction and salary look negatively associated in this data even if they are independent among all hires?
      AnswerStaying is a common effect: satisfaction → stays ← salary. The dataset keeps only units with "stays = 1", which conditions on a collider. Among the people who stayed, a low salary must be balanced by high satisfaction more often (Berkson's paradox).
    6. Why can a faithful-looking dataset still come from a graph with an arrow A→CA \to C, although AA and CC are uncorrelated?
      AnswerTwo causal paths can cancel exactly, for example a direct effect aa and an indirect effect bcbc with a+bc=0a + bc = 0. Then the distribution is not faithful: it has an independence that the graph does not imply.
    Recall cardsAnswer in your head first, then reveal. Add the cards to your review deck to see them again just before you would forget.
    1. What is a structural causal model?

    2. What does a missing arrow A→BA \to B claim in a causal graph?

    3. Write the Markov factorization of a DAG.

    4. In a chain A→B→CA \to B \to C, are AA and CC independent given BB?

    5. In a collider A→B←CA \to B \leftarrow C, what happens when you condition on BB?

    6. A,C∼N(0,1)A, C \sim \mathcal N(0, 1) independent, B=A+C+UBB = A + C + U_B with unit noise. What is the partial correlation of AA and CC given BB?

    7. When is a path blocked by a set ZZ?

    8. What is faithfulness, and when does it fail?

    9. What is a backdoor path from TT to YY?

    10. Why is Berkson's paradox a case of collider bias?

    Open the review →

    9. Interview angle #

    • "What is a collider and why should you not control for it?" A common effect of two variables on a path. Controlling for it (or for one of its descendants) opens the path and creates an association between its causes. Example: controlling for "reviews" when estimating the effect of ads on sales, if both ads and sales cause reviews.
    • "Explain Berkson's paradox with a hiring example." Hiring depends on skill + charisma. Among hired people, the two are negatively correlated, although they are independent among applicants: a low-skill hire must have high charisma to be hired.
    • "Draw the graph of a recommender's feedback loop." Past recommendations → items shown → clicks; user preference → clicks; clicks → next model → next recommendations. Training on logged clicks conditions on "item was shown", which depends on the old model; the logged data are a selected sample.
    • "Can data tell you the direction of an arrow?" Not from independences alone between two variables. With three variables, a collider A→B←CA \to B \leftarrow C has a different pattern of independences than a chain or fork, so some directions can be found (lesson 10).

    10. Practice #

    The notebook for this lesson has five exercises, each with a check cell and a folded solution:

    1. sample_scm(parents, coefs, n, seed): sample from a linear-Gaussian SCM given as a dictionary of parents.
    2. d_separated(parents, a, b, Z): d-separation by path enumeration; checked on the presets of this lesson and against the independences found in large samples of random graphs.
    3. partial_corr from the inverse covariance matrix and a Fisher zz-test; check the collider value −1/2-1/2.
    4. Berkson's paradox: simulate talent and looks, select the top share, and plot the correlation inside the selection against the share.
    5. List all conditional independences that the sprinkler graph implies (pairs with sets of size up to 2) and test them on a binary sample of 20,000 units.

    11. Watch and read #

    Chains, forks, colliders and d-separation, with the same rules as this lesson.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The fork, the pipe (chain), the collider and the descendant, with simulations.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    Structural causal models and the modularity assumption behind graphs.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    • Judea Pearl, Madelyn Glymour and Nicholas Jewell, Causal Inference in Statistics: A Primer (Wiley 2016), ch. 2; companion site with solutions.
    • Brady Neal, Introduction to Causal Inference, free course notes, ch. 3 (graphs, d-separation).
    • Jonas Peters, Dominik Janzing and Bernhard Schölkopf, Elements of Causal Inference (MIT Press 2017, open access), ch. 6.1–6.5 (SCMs, Markov property, faithfulness).
    • Miguel Hernán and James Robins, Causal Inference: What If, free book, ch. 6 (graphs) and ch. 8 (selection bias).
    • Daphne Koller and Nir Friedman, Probabilistic Graphical Models (MIT Press 2009), ch. 3 (d-separation, Bayes-ball).