learn-causal-inference-with-phoebe / Practitioner session 4 of 10
Learn Causal Inference with Phoebe · Practitioner session 4 of 10

The front door

Session 3 ended on the unhappy case: a common cause of treatment and outcome that nobody measured, no adjustment set that satisfies the back-door criterion, and the honest conclusion that the effect is not identified from this data. There is one escape from that, and it is genuinely surprising. If the treatment reaches the outcome only through a mediator you CAN measure, the effect is identified after all, without ever adjusting for the thing you could not see. Tonight is the escape, the three conditions that license it, and the reason Kestrelmark does not qualify.

🔴 Hardest Data scientists and analysts 45 min
0-3 · Welcome 3-22 · When the back door is shut for good 22-40 · Build-along: the two-stage calculation 40-45 · Q&A
Part 0

The situation this result is for

One specific dead end: the back-door paths are real, at least one of them runs through a variable nobody recorded, and no set of measured variables blocks it. Adjustment has nothing to offer. Most of the time that is the end of the analysis and the right move is to say so out loud. Occasionally the graph has a second route, and the second route is worth knowing about because it is easy to miss and easy to misapply.

Live = presented in the 45 minutes Self-study = the full depth, after class 🔍 Every diagram zooms

★ What you walk out with tonight. The three conditions of the front-door criterion, written down in a form you can check against an edge list rather than by squinting at a picture. A working two-stage calculation on a graph where it is valid, scored against a truth known by construction. And the professional habit that matters more than the formula: checking condition (i) first, watching it fail on your own graph, and saying so instead of shipping a number.

LiveA confounder you cannot measure does not always end the analysis3 min▶

The back-door criterion asks for a set of measured variables that blocks every path from treatment to outcome starting with an arrow into the treatment. When the only such path runs through an unmeasured common cause, no set does the job, and the standard conclusion follows: the effect is not identified from this data, and more rows will not change that.

The front door takes a different route to the same quantity. Instead of trying to make the treated and untreated groups comparable, it stops comparing them. It measures how much the treatment moves an intermediate variable, then how much that intermediate variable moves the outcome, and multiplies. Neither of those two measurements requires knowing anything about the unmeasured confounder, and the product is the effect you wanted.

Real world

The textbook case is smoking and lung cancer with an unmeasured genetic predisposition arguing for both. Tar deposits in the lung sit on the path from smoking to cancer, and nothing about the genotype reaches the cancer except through the tar. Under that graph, and only under that graph, the effect is recoverable without ever measuring the gene.

Self-studyThe vocabulary for tonight3 min▶
  • Front-door criterion - a set of graph conditions under which the effect of X on Y is computable from measured variables even though every back-door path is blocked by something unmeasured.
  • Mediator on the whole path - a variable M through which every directed path from X to Y must pass. Not "a mediator", but the only route.
  • Stage 1 - the effect of X on M. Identified because nothing unmeasured confounds that pair.
  • Stage 2 - the effect of M on Y, with X held fixed. Identified because X blocks the back-door paths from M to Y.
  • do-calculus - three rewriting rules that decide, for any graph and any query, whether the query can be turned into an expression in observed quantities. The front-door result is one of its consequences.
  • Identifiable - the estimand can be written as a function of the observed distribution given the graph. Still says nothing about how well it can be estimated from a finite sample.
Part 1 · covers the escape and its three conditions

A confounder you cannot measure does not always end the analysis

10 min live

The shape below is the whole result. An unmeasured U feeding both the treatment and the outcome, and a mediator M that the treatment must pass through to reach the outcome at all. The back door is shut for good; the front door is open.

The one graph shape the front door is for U unobserved back door: cannot be closed Treatment X Mediator M Outcome Y stage 1: X moves M stage 2: M moves Y nothing confounds this pair hold X fixed and it is clean front-door estimate = stage 1 x stage 2 U is never measured and never adjusted for. Both stages are measurable without it.
🔍 Click to zoom - the back door is shut, and the effect is still recoverable through the mediator.
LiveThe three conditions, stated so you can check them4 min▶

A mediator M qualifies for the front door, relative to the ordered pair X and Y, when all three of these hold at once. They are conditions on the graph, not on the data, and each one is a separate opportunity to be wrong.

  • (i) M intercepts every directed path from X to Y. Every route by which the treatment reaches the outcome passes through M. Delete M from the graph and no directed path from X to Y survives.
  • (ii) There is no unblocked back-door path from X to M. Nothing unmeasured confounds the treatment and the mediator, so stage 1 is honest as it stands.
  • (iii) Every back-door path from M to Y is blocked by X. Conditioning on the treatment is enough to clean up stage 2, which is why stage 2 is measured with X held fixed rather than raw.

Notice what is not in the list: any requirement about U. U can be arbitrarily strong, arbitrarily strange, and completely unrecorded. The criterion never touches it. That is the whole surprise.

LiveWhy multiplying two honest pieces gives an honest whole3 min▶

Take the two stages one at a time. Stage 1 asks how much the treatment shifts the mediator. Under condition (ii) there is nothing confounding that pair, so the plain comparison of M across levels of X is already the causal quantity. Stage 2 asks how much the mediator shifts the outcome, and under condition (iii) holding X fixed blocks every contaminating path into that comparison, so it too is causal.

Condition (i) is what lets you glue them together. If M is the only route, then every unit of effect that leaves X arrives at Y by way of M, and the total is the amount of movement in M multiplied by the amount of outcome each unit of movement buys. Break condition (i) and some of the effect travels by a road you never measured, so the product is not the total: it is only the portion that happens to go through M.

Read the formula as a sentence before you read it as algebra. "How far does the treatment push the mediator, and what is each unit of push worth at the outcome." Anyone in the room can check that sentence against the business. Nobody can check a summation.

Self-studyWhat the criterion buys and what it does not4 min▶
  • It buys identification, not precision. The effect can be written as a function of observed quantities. Whether 5,000 rows pin that function down tightly is a separate question and a separate discipline.
  • It buys nothing if M is measured badly. A noisy or partial measurement of the mediator attenuates stage 1 and stage 2 at once, and the two errors multiply rather than partly cancelling.
  • It buys nothing if there is a second unmeasured confounder between M and Y. That is condition (iii) failing, and it is the second most common failure after condition (i).
  • It does not need randomisation anywhere. Which is exactly why it is attractive, and exactly why it deserves a hostile review before it is used.
  • Fitting it well on real data - variance, standard errors, and the estimator choices for each stage - is the experimentation course's territory. learn-experimentation-with-phoebe owns every observational estimator. The question here stops at whether the quantity exists.
Part 2 · covers the failure mode and the general machinery

Why it is rarer than it looks, and the three rules behind it

8 min live

Condition (i) is the one that fails, and it fails almost every time somebody reaches for this in an applied setting. A treatment usually has more than one way of reaching its outcome, and a single extra arrow is enough to disqualify the whole calculation. Kestrelmark is a textbook example of the disqualification.

One extra arrow, and the criterion no longer applies U unobserved Email X Opened M Spend Y stage 1 still fine stage 2 still fine direct arrow: X reaches Y without M Condition (i) FAILS: a directed path from X to Y skips the mediator entirely. Kestrelmark is this graph. The two-stage product would miss the direct arrow and understate.
🔍 Click to zoom - Kestrelmark's email reaches spend two ways, so the front door does not apply.
LiveKestrelmark does not qualify, and saying so is the work4 min▶

The Kestrelmark graph from session 1 has the email pointing at opened, opened pointing at spend, and the email also pointing straight at spend. That third arrow was defended out loud in session 1: even unopened, the sender name in an inbox is a reminder, and a reminder moves purchases. It is a modest claim and a hard one to argue away.

That single arrow is fatal to the front door here. Condition (i) demands that opened intercept every directed path, and the direct arrow is a directed path it does not intercept. The two-stage product would recover only the part of the effect that flows through opening, and would report it as the whole thing.

Which is fine, because Kestrelmark does not need the front door. Its back-door paths run through season and tenure, both of them measured, and adjusting for that pair lands at 6.56 against a truth of 6.23. The front door is for the case where the back door is unavailable, and reaching for it when the back door is open is a way to be clever instead of correct.

Real world

The failure that reaches production looks like this: somebody finds a mediator with a strong first stage, runs the product, gets a plausible number, and never writes down the sentence "the treatment cannot reach the outcome any other way". A reviewer who asks for that one sentence in writing catches most of these in under a minute.

LiveThe three rules of do-calculus, named3 min▶

The back door and the front door are not two unrelated tricks. Both fall out of a single piece of machinery: three rewriting rules, due to Pearl, that say when a query containing an intervention can be transformed into an expression containing only observed quantities. Their names are worth carrying even without their derivations.

  • Rule 1, insertion and deletion of observations. When a variable is irrelevant to the query given what is already conditioned on, it can be dropped from the expression.
  • Rule 2, exchanging an action for an observation. When the right paths are blocked, forcing a variable and merely observing it are the same thing. This is the rule the back-door criterion is a special case of.
  • Rule 3, insertion and deletion of actions. When an intervention has no route to the query, it can be removed from the expression entirely.

Applied repeatedly, these three rules are complete: if a query is identifiable from a given graph, some sequence of them will produce the expression, and if no sequence does, the query is not identifiable. The front-door formula is one such sequence, worked out once and then reused. Tonight uses the result and leaves the derivation alone, which is the right trade for a working practitioner.

Self-studyAn honest summary of where the front door sits4 min▶

It is a real and beautiful result. It says something that felt impossible before Pearl wrote it down: that an unmeasured confounder of arbitrary strength need not be fatal, provided the mechanism is fully observed. Nothing in this track is more counterintuitive on first reading.

It also applies to a narrow class of graphs, and the narrowness is structural rather than accidental. Condition (i) requires that the mechanism be complete, and real treatments are rarely tidy enough for that. Marketing touches work through several channels. Drugs have side effects. Policies change behaviour in ways nobody enumerated. Each extra route is another directed path that M fails to intercept.

  • The professional move is to check, not to reach. Three conditions, checked against the edge list, in the order (i), (iii), (ii). Condition (i) fails most often, so test it first and stop early.
  • A failed check is a finding. "The front door does not apply because the treatment also reaches the outcome directly" is a defensible sentence in a review, and it is worth more than a number nobody can justify.
  • A passed check is the start of a different conversation. How well is M measured, how complete is it, and who signs off that the mechanism has no second route.
  • The alternative when it fails is not a cleverer formula. It is a design change: find an instrument, run an experiment, or state that the effect is not identified. Session 9 covers the fourth option, which is to bound how wrong you might be.
Build-along

The two-stage calculation, and then breaking it

★ 18 min · everyone builds

Four steps. Encode a graph where the front door genuinely applies, check the three conditions in code rather than by eye, compute the product against a truth you wrote yourself, then add one arrow and watch the same code report a number that is wrong by exactly the size of the arrow.

Step 1. Encode the graph as an edge list. Not a picture. A list of pairs that a function can walk. Everything tonight is a query against this list, which is the difference between checking a criterion and feeling that it probably holds.

Step 2. Write the three conditions as three functions. Each returns True or False against the edge list. Condition (i) is a search over directed paths; conditions (ii) and (iii) need back-door paths and a blocking rule, which is the same machinery session 3 built.

Step 3. Generate data from a model whose true effect you set by hand, with an unmeasured confounder strong enough that the naive comparison is visibly wrong. Compute stage 1, compute stage 2 with the treatment held fixed, multiply, and compare with the truth.

Step 4. Add the direct arrow and run everything again. The condition check flips to False and the product no longer matches the truth. The size of the miss is the size of the arrow you added, which is the cleanest possible demonstration of what condition (i) is protecting.

★ Try it now - the graph, and the three conditions as code # frontdoor.py - step 1 and step 2. The graph is the input, not the picture. EDGES = [ ("u", "x"), # unmeasured common cause of treatment and outcome ("u", "y"), ("x", "m"), # treatment moves the mediator ("m", "y"), # the mediator moves the outcome ] def children(g, node): return [b for (a, b) in g if a == node] def parents(g, node): return [a for (a, b) in g if b == node] def descendants(g, node, acc=None): acc = set() if acc is None else acc for c in children(g, node): if c not in acc: acc.add(c) descendants(g, c, acc) return acc def directed_paths(g, src, dst, seen=()): if src == dst: yield [src] return for nxt in children(g, src): if nxt not in seen: for tail in directed_paths(g, nxt, dst, seen + (src,)): yield [src] + tail def any_paths(g, src, dst, seen=()): """every path, ignoring which way the arrows point""" if src == dst: yield [src] return for nxt in sorted(set(children(g, src)) | set(parents(g, src))): if nxt not in seen: for tail in any_paths(g, nxt, dst, seen + (src,)): yield [src] + tail def blocked(g, path, z): for i in range(1, len(path) - 1): a, b, c = path[i - 1], path[i], path[i + 1] collider = (a, b) in g and (c, b) in g if collider: if b not in z and not (descendants(g, b) & z): return True # a closed collider blocks the path elif b in z: return True # a chain or fork closed by conditioning return False def back_door_paths(g, src, dst): """paths whose first edge points INTO src""" return [p for p in any_paths(g, src, dst) if (p[1], src) in g] def condition_i(g, x, y, m): return all(m in p for p in directed_paths(g, x, y)) def condition_ii(g, x, m): return all(blocked(g, p, set()) for p in back_door_paths(g, x, m)) def condition_iii(g, m, y, x): return all(blocked(g, p, {x}) for p in back_door_paths(g, m, y)) def front_door_ok(g, x="x", y="y", m="m"): checks = { "(i) M intercepts every directed path X to Y": condition_i(g, x, y, m), "(ii) no unblocked back door from X to M": condition_ii(g, x, m), "(iii) back doors from M to Y are shut by X": condition_iii(g, m, y, x), } for name, ok in checks.items(): print(f"{'PASS' if ok else 'FAIL'} {name}") return all(checks.values()) front_door_ok(EDGES) # PASS (i) M intercepts every directed path X to Y # PASS (ii) no unblocked back door from X to M # PASS (iii) back doors from M to Y are shut by X

Condition (ii) passes for an interesting reason. The only path from X to M that starts with an arrow into X is x from u to y to m, and Y on that path is a collider: U points into it and M points into it. An unconditioned collider blocks its own path, so nothing needs doing. Session 2's shape is doing the work here.

★ Try it now - step 3, the two stages against a truth you set yourself # frontdoor.py continued. True effect of x on y is 0.6 * 4.0 = 2.4, by construction. import numpy as np rng = np.random.default_rng(7) n = 20000 u = rng.normal(size=n) # never used again x = (0.9 * u + rng.normal(size=n) > 0).astype(float) # confounded treatment m = 0.6 * x + 0.5 * rng.normal(size=n) # stage 1 coefficient 0.6 y = 4.0 * m + 2.0 * u + rng.normal(size=n) # stage 2 coefficient 4.0 TRUTH = 0.6 * 4.0 def ols(design, target): beta, *_ = np.linalg.lstsq(design, target, rcond=None) return beta # stage 1: how far does the treatment push the mediator stage1 = m[x == 1].mean() - m[x == 0].mean() # stage 2: what is one unit of mediator worth at the outcome, with X held fixed design = np.column_stack([np.ones(n), m, x]) stage2 = ols(design, y)[1] naive = y[x == 1].mean() - y[x == 0].mean() print(f"truth {TRUTH:.2f}") print(f"naive {naive:.2f}") # about 4.5: U is inflating it badly print(f"stage 1 {stage1:.2f}") # about 0.60 print(f"stage 2 {stage2:.2f}") # about 4.00 print(f"front door {stage1 * stage2:.2f}") # about 2.40, and U was never touched
★ Try it now - step 4, add the direct arrow and watch it break # frontdoor.py continued. Same U, same X, same M. One new arrow: x straight to y. BROKEN = EDGES + [("x", "y")] front_door_ok(BROKEN) # FAIL (i) M intercepts every directed path X to Y # PASS (ii) no unblocked back door from X to M # PASS (iii) back doors from M to Y are shut by X y2 = 5.0 * x + 4.0 * m + 2.0 * u + rng.normal(size=n) TRUTH2 = 5.0 + 0.6 * 4.0 # direct 5.0 plus mediated 2.4 = 7.4 stage2b = ols(np.column_stack([np.ones(n), m, x]), y2)[1] estimate = stage1 * stage2b print(f"truth {TRUTH2:.2f}") # 7.40 print(f"front door {estimate:.2f}") # about 2.40 print(f"miss {TRUTH2 - estimate:.2f}") # about 5.00, exactly the arrow added # The arithmetic did not break. The graph did. Stage 2 still recovers 4.0 because # holding x fixed is still enough for that pair; the product is simply no longer # the whole effect, because the whole effect no longer travels through m.

★ What just happened. The estimate did not degrade gracefully or get noisier. It stayed confident, stayed stable, and reported the mediated portion as though it were the total, missing by precisely the coefficient on the arrow the check flagged. There is no diagnostic in the data that would have caught it. The edge list caught it in three lines.

Homework

Before session 5

30 min
  1. Run the three condition checks against your own graph from session 1, with your real treatment and outcome and the best mediator candidate you have. Record which condition fails first.
  2. Write the condition (i) sentence out in full for that candidate: "the only way X reaches Y is through M". Take it to one person who knows the mechanism and see whether they can name a second route in under a minute. They usually can.
  3. Find one published analysis in your field that uses a mediator to argue causation. Check whether it states condition (i) anywhere, in any words. Note what it says instead.
  4. Add the front-door check to the same file as your identification check from session 3, so a future graph edit re-runs both without anybody remembering to.
Check yourself

Three questions

Kestrelmark's email points at opened, opened points at spend, and the email also points straight at spend. Can the front door be used with opened as the mediator?

Condition (i) is not a matter of degree. One unintercepted directed path disqualifies the calculation, and the miss is exactly the size of that path. Kestrelmark does not need the front door anyway: its back doors run through season and tenure, both measured.

What does the front-door criterion require you to know about the unmeasured confounder U?

That is the surprise of the result. All three conditions are statements about paths in the graph. None of them mentions U's strength, distribution, or measurability.

A colleague proposes the front door for a marketing treatment, showing a strong first stage and a clean second stage. Which check should be run first?

Strong stages are evidence of nothing when the mechanism is incomplete. Marketing treatments almost always reach the outcome through more than one channel, which is exactly the shape condition (i) rules out.

Sources covered

What tonight maps to

✓ The front-door criterion and its three conditions Stated formally, checked in code against an edge list, and demonstrated on a graph where all three hold.
✓ When an unmeasured confounder blocks the back door The dead end from session 3, and the one graph shape that escapes it without measuring the confounder.
✓ Why condition (i) usually fails Kestrelmark's direct email-to-spend arrow disqualifies it, and the measured miss equals the coefficient on that arrow.
◐ Full do-calculus The three rules are named as the general machinery that decides identifiability. They are not derived here, by design.
◐ The back-door criterion, stated formally Session 3. Tonight assumes it and starts from the case where no valid set exists.
· Propensity scores, IPW, doubly robust, difference-in-differences, synthetic control, DoWhy Not covered by design, in any session. Fitting an estimator to an identified quantity belongs to learn-experimentation-with-phoebe; identification is the question here.

Session 4 cheat sheet

What it is forAn unmeasured common cause shuts every back door and no adjustment set exists.
The escapeMeasure how X moves M, how M moves Y with X fixed, and multiply.
Condition (i)M intercepts every directed path from X to Y. Delete M and no route survives.
Condition (ii)No unblocked back-door path from X to M, so stage 1 is honest raw.
Condition (iii)Every back door from M to Y is shut by X, so stage 2 holds X fixed.
U is never mentionedNo condition constrains its strength or asks for a proxy. That is the surprise.
Check (i) firstIt fails most often. Kestrelmark's direct email-to-spend arrow fails it.
A failed check is a findingSay the front door does not apply. That beats a number nobody can defend.