DS701 Session 18 — Wed Nov 4, 2026
Name the three elementary structures every path in a causal DAG is built from, and for each say (i) what the middle node is called and (ii) whether the path through it is open or blocked by default, and what happens when you condition on that middle node.
In the tutoring example, \(X\) = tutoring and \(Y\) = final grade, with \(\text{GPA}_{\text{prior}} \to X\), \(\text{GPA}_{\text{prior}} \to Y\), \(X \to \text{Hours} \to Y\) and \(X \to \text{HonorRoll} \leftarrow Y\). A colleague argues that adjusting for \(\{\text{GPA}_{\text{prior}}, \text{Hours}, \text{HonorRoll}\}\) must be at least as good* as adjusting for \(\{\text{GPA}_{\text{prior}}\}\) alone, “because controlling for more can only help.” Using the backdoor procedure, explain why the colleague is wrong about the total effect of tutoring — say what each of Hours and HonorRoll does to the estimate.*
Lecture I showed that randomization removes selection bias; this lecture showed that adjusting for a valid backdoor set does the same job with observational data. Suppose you believe there is a confounder you cannot measure (e.g. “motivation” driving both who takes a training program and later earnings). Explain in a sentence why regression adjustment cannot fix this, then name one of the three natural-experiment designs from the lecture, say in a sentence what “as good as random” variation it exploits, and state the key assumption it relies on instead.

Effects flow along directed paths; spurious association along the others. Domain knowledge draws the graph — data cannot — but once drawn, it tells you exactly what to control for.

A path is blocked if at least one interior node is blocked; \(X\) and \(Y\) are independent given \(S\) when every path between them is blocked. Sanity check: \(X \leftarrow A \to Y\) is open (fork) — the ice-cream/temperature confounding of Lecture I; condition on \(A\) and it closes.
| structure | middle node | adjust for it? | why |
|---|---|---|---|
| fork \(X \leftarrow Z \to Y\) | confounder | yes | blocks the spurious backdoor path |
| chain \(X \to M \to Y\) | mediator | no* | it is the effect you want (overcontrol) |
| collider \(X \to C \leftarrow Y\) | collider | no! | conditioning creates association |
* unless you specifically want the direct, not the total, effect.
Talent and looks: independent by construction (corr \(\approx 0.00\)), yet among the famous corr \(\approx -0.55\) — restricting to the famous conditions on the collider talent \(\to\) famous \(\leftarrow\) looks. Selection is conditioning.
So “throw every variable into the regression” is wrong. Today’s stretch section makes you watch it go wrong on data you generated yourself.
A backdoor path starts with an arrow into \(X\) — confounding in graph language. \(S\) is a valid adjustment set if it blocks every backdoor path and contains no descendant of \(X\).
Then — and only then — pick an estimator. Identification and estimation are separate decisions.

\(A \to X,\ A \to Y,\ M \to X,\ M \to D,\ D \to Y,\ X \to W,\ W \to Y\)
Y ~ X + A + M recovers the total effect; Y ~ X + A + M + W does not.

Lecture simulation: \(Y = 3T + 2Z + \varepsilon\), sicker (\(Z\)) more likely treated.
Given a valid \(S\) (ignorability), any of these recovers the effect:
Same \(S\), same answer. A wrong \(S\) gives a wrong answer with a tight standard error — the estimator cannot rescue a bad graph.
Adjustment only blocks paths through variables you measured. Otherwise look for treatment variation that is as good as random:
Every estimate still rests on assumptions data cannot verify — ignorability, positivity (\(0 < e(S) < 1\)), SUTVA, the graph itself — so state them and stress-test them (sensitivity analysis). Workflow: draw the graph → identify → estimate → refute.
Next session: we leave causal questions for prediction — neural networks: forward pass, loss, gradient descent, by hand.
Goal: on five DAGs (drawn with networkx), list every backdoor path, mark it open or blocked, code the two rules into a checker, and propose one valid and one invalid adjustment set per DAG. Then simulate data from one of those DAGs with a known effect and estimate it four ways — naive, correct set, wrong set (mediator / collider), inverse-propensity weighting — and see which ones recover the truth.
numpy, pandas, matplotlib, networkx, statsmodels, scikit-learn.The activity notebook goes live on the day of the lecture. Colab is optional — you can also open it on GitHub and run it locally.
Full lecture notes: Causal Inference II: Causal Graphs and Estimating Effects