Causal Inference 09: The Measurement Program

A year of learning, budgeted like the investment it is. Notebook 08 chose one experiment well. A measurement program is a different problem: seven channels, finite testing capacity, cool-downs, seasons — and evidence that quietly expires while you're busy elsewhere. This page mirrors nbs/causal/causal_09_planning_the_measurement_series.ipynb: the framework prices every candidate test in two currencies — EIG (expected information gain, nats: what a feasible test would teach) and EVOI (expected value of information, KPI units: what knowing is worth to the budget decision) — under one ceiling, EVPI, the value of perfect information about everything. A channel can be wildly uncertain and still worth nothing to test — if no plausible answer would change the allocation.

1.17 nats
Print's EIG — top priority (EVOI 634 KPI units, quadrant test_now): the engine lands where rung 7 pointed
1,624
EVPI in KPI units — 4.4% of the optimal-budget value (36,638): the rational ceiling of the entire measurement budget
0.70 nats
what a fresh Radio test would buy, 84 weeks after its late-2022 readout (52-week half-life) — already RETEST-DUE
15.5
TV's EVOI — "deprioritize". Correct for known unknowns, blind to the hidden bias rung 2 flagged: hence a validation track

1 — The priority grid

Inputs: the current posterior (the series' rung-2 fit on Veranda's seven-channel history) and the evidence ledger from notebook 07 — Radio's go-dark readout window ended 2022-11-28, Display's off-panel holdout ended 2024-04-22. Planning date: 2024-07-01. Per channel, the engine simulates a feasible national-pulse test, computes EIG against the channel's current ROI posterior (decayed where evidence exists), and EVOI by re-optimizing the budget across simulated readouts:

channel spend share ROI posterior EIG (nats) EVOI (KPI) quadrant evidence
Print5.2%0.82 ± 0.571.17634test_now
Radio8.1%0.66 ± 0.381.03591test_now83 wk ago → retest due
Display12.6%0.76 ± 0.250.53158test_now10 wk ago
Social15.5%0.76 ± 0.180.3731learn_cheaply
Search19.6%0.55 ± 0.110.2542monitor
TV28.2%0.66 ± 0.080.1015deprioritize
Video10.7%2.12 ± 0.390.250.6deprioritize

Measurednbs/artifacts/causal_09_program.json (grid order = priority order). Print — the channel whose split the Radio test resolved onto shaky ground in notebook 07 — is the program's top priority, and the engine found it independently of rung 7's narrative. Note Video: one of the widest ROI posteriors on the board (2.12 ± 0.39), a respectable EIG of 0.25 nats — and an EVOI of 0.6. Knowing more about Video changes nothing the budget would do.

from mmm_framework.planning.priority import compute_experiment_priorities
from mmm_framework.planning.eig import channel_half_life, decayed_sigma, reexperiment_due

grid, portfolio = compute_experiment_priorities(
    mmm,
    evidence={"Radio": {"end_date": "2022-11-28"},
              "Display": {"end_date": "2024-04-22"}},
    as_of="2024-07-01", max_draws=150, random_seed=42,
)
# portfolio["evpi"] -> 1,624 KPI units (4.4% of the optimal-budget value)

due, fresh_eig = reexperiment_due(0.10, 84, channel_half_life("Radio"),
                                  sigma_exp=0.10)
# -> a fresh Radio test would buy 0.70 nats: retest due

Measured — the measurement quadrant. Bubble size = spend share, color = the engine's verdict. The diagnostic corners: Print and Radio (high both — test now), Video (informative but worthless — deprioritize), TV (neither — the tight posterior of the biggest spend line). EIG says what a test would teach; EVOI says whether anyone should pay for the lesson.

2 — An honest asterisk the grid needs

⚠️ EVOI prices known unknowns

TV sits in deprioritize — its ROI posterior is tight (0.66 ± 0.08), so a test teaches little and moves no budget. But rung 2's sealed key showed TV carries a residual bias the model doesn't know about (its learning diagnostic flagged beta_TV as relocated). EVOI is computed from the posterior, so it cannot price a bias the posterior doesn't represent. A mature program runs two tracks: the EVOI track above, and a validation track that occasionally tests confident channels precisely because they're confident — triggered by diagnostics (relocation flags, refutation failures, tension checks), not by uncertainty. Notebook 10 shows a validation-track test paying off.

3 — EVPI: the ceiling on the learning budget

Summing what perfect information about everything would be worth gives the program its budget ceiling: EVPI = 1,624 KPI units, against an optimal-budget value under current knowledge of 36,638 — the program's rational scale is 4.4% of the value it protects. Any measurement plan costing more than EVPI is, by construction, destroying value — no matter how scientific it feels. And any plan costing far less is probably leaving correctable bias in the allocation.

4 — Evidence decays

A readout is a photograph, not a covenant. Markets drift — creative wears out, auctions reprice, competitors move — so the information an experiment bought erodes on a half-life. The framework re-inflates the posterior sd as \( \sigma^2(t) = \sigma_0^2 \, e^{\lambda t} \) with \( \lambda = \ln 2 / h \), and re-flags a channel for testing when a new feasible test would again clear the EIG bar. Radio (half-life 52 weeks, tested 84 weeks before the planning date — its variance has roughly tripled since) has decayed enough that a fresh test would buy 0.70 nats — over the bar, retest due. Display (half-life 26 weeks, tested 10 weeks ago) is still fresh.

The framework's decay law, drawn exactlydecayed_sigma from planning/eig.py with each channel's default half-life (channel_half_life: Radio 52w, Display 26w) and the notebook's post-experiment sds (Radio 0.10, Display 0.15). The dotted verticals mark where each channel actually stands at the 2024-07-01 planning date. "We tested that in 2022" is a date, not an excuse.

5 — The calendar

Scores in hand, the calendar is a constrained packing problem: a greedy EVOI-per-week schedule under the program's real constraints — one national test at a time, per-channel cool-downs (rung 8), a Q4 freeze (no experiments in the holiday quarter, program weeks 13–26), re-tests when decay triggers. The TV validation test is scheduled by policy, not EVOI — it's pinned to the last slot, using rung 8's 16-week design.

Measurednbs/artifacts/causal_09_program.json (solid = test, faint = cool-down, shaded band = Q4 freeze). The Print geo holdout starts immediately; the freeze pushes the Radio re-test to week 26; Display and Social follow. The EVOI-track tests finish by week 56; the policy-pinned TV validation runs weeks 57–73, spilling into the next cycle — cool-downs and a frozen quarter stretch five tests across substantially more calendar than the naive sum of their durations. Calendar is the scarcest thing the program has.

6 — The program's memory

Every fitted model in the loop persists a per-run metrics snapshot — ROI posteriors, response curves, the EIG/EVOI portfolio, allocation gaps — so next quarter's planning starts from recorded state, not from whoever remembers the last deck. compute_run_metrics is the same snapshot the platform stores per fit:

from mmm_framework.planning.history import compute_run_metrics

snapshot = compute_run_metrics(mmm, max_draws=100, random_seed=42)
# keys: approximate, channels, fit_method, n_draws, portfolio,
#       response_curves, schema_version   (7 channels tracked; schema v2;
#       fit method nuts, approximate False)

7 — The program's operating rules

  1. Price tests in both currencies. EIG says what you'd learn; EVOI says whether learning changes any decision. Test where both are high.
  2. EVPI is the budget. The whole program should cost a fraction of the value of perfect information — if it doesn't, you're doing science for sport.
  3. Evidence expires. Half-lives and re-test triggers turn "we tested that in 2021" from an excuse into a date.
  4. Keep a validation track. EVOI can't see biases the posterior doesn't know it has. Diagnostics-triggered tests on confident channels are the program's insurance policy.
  5. Write the state down. Snapshots make the loop resumable by people who weren't in the room.

Check your understanding

Commit to an answer before opening each one.

Video has one of the widest ROI posteriors on the board (2.12 ± 0.39) and a respectable EIG (0.25 nats). Why is its EVOI only 0.6 KPI units?

Because EVOI doesn't price uncertainty — it prices decision change. The engine simulates plausible readouts from the current posterior and asks how much the re-optimized budget improves under each. For Video, essentially every plausible answer leaves the allocation where it already is, so knowing the true number is worth almost nothing this year. Uncertainty without decision leverage is epistemically interesting and economically worthless — which is exactly why the grid needs two axes. Test where both are high.

TV is the biggest line on the media plan (28% of spend) and the CFO doubts it. The grid says "deprioritize". Who's right?

Both — about different questions. On known unknowns the grid is right: TV's ROI posterior is the tightest on the board (0.66 ± 0.08), so a feasible test teaches little (EIG 0.10 nats) and moves almost no budget (EVOI 15.5). But rung 2's sealed key showed TV carries a bias the posterior doesn't represent, and EVOI cannot price what the posterior can't see. That is the validation track's job: test confident channels on a diagnostics trigger (relocation flags, refutation failures), by policy — which is why the calendar still ends with a 16-week TV validation test despite its EVOI.

Radio was properly tested with a well-designed go-dark in late 2022. Why won't the engine just reuse that readout?

Because the information is perishable even when the readout was perfect. Radio's post-experiment sd (0.10) re-inflates on a 52-week half-life — \( \sigma^2(t) = \sigma_0^2 e^{\lambda t} \) — and by the 2024-07-01 planning date the readout is 84 weeks old: about 1.6 half-lives, so the variance has roughly tripled. A fresh feasible test would buy 0.70 nats, above the re-test bar, so the engine flags retest_due. The decay clock isn't cynicism about the old test; it's a model of a drifting market. A program that never re-tests is spending this year's budget on a 2022 world.

💡 Run it yourself

This page mirrors nbs/causal/causal_09_planning_the_measurement_series.ipynb — notebook 9 of 11 in the Causal Inference in Practice series (brand: Veranda Home; synthetic worlds with sealed answer keys; every claim graded by an assert). All numbers from nbs/artifacts/causal_09_program.json, produced by nbs/causal/causal_09_planning_the_measurement_series.ipynb. Previous: 08 · Designing the Next Experiment. Next: 10 · The Closed Loop — the capstone: three full cycles of fit → prioritize → design → measure → calibrate, graded against the sealed key at every step. Source: github.com/redam94/mmm-framework.