Heterogeneous effects and causal ML: meta-learners, double ML and causal forests
Before this lesson: potential outcomes and the CATE (lesson 02); conditional exchangeability, positivity, the propensity score and AIPW (lesson 05); regularization (ridge and lasso), cross-validation, decision trees, random forests and boosting (standard supervised learning); projections (linear algebra 03) help for section 3.3. Time: about 110 minutes, plus the notebook. This is the heaviest lesson of the track. The two folded deeper blocks can be skipped on a first reading.
Why this matters #
Many decisions are about whom to treat, not whether to treat: which users get a discount, which patients get a drug with side effects, which job seekers get a training program. A model that predicts "who will buy" or "who will churn" answers the wrong question. The right question is "for whom does the treatment change the outcome?". This is uplift modeling in marketing and personalised medicine in health. Tech companies look for effects that differ between user groups in every large A/B test.
The second use is estimating one effect with many covariates. With 100 confounders, a linear regression can be badly misspecified, and a plain ML model gives biased effects (section 3.3). Double/debiased machine learning (Chernozhukov et al. 2018) is now a standard tool in economics, epidemiology and industry: it gives a -consistent estimate and a valid confidence interval while gradient boosting or random forests model the confounding. The ideas of this lesson (orthogonal scores, cross-fitting, honest estimation) also appear in off-policy evaluation (lesson 11) and in modern semiparametric statistics.
1. Predict first #
2. The picture #
2.1 The effect is a gap between two curves #
Take one covariate . The outcome regressions are (the average outcome of controls with features ) and . Under the assumptions of lesson 05, the CATE is the vertical gap between the two curves:
Why is this hard, even with good ML models? Three reasons.
- The gap is small and simple; the curves are big and complex. In the figure below, the baseline goes up and down by about 4 units, while the effect changes slowly between and . A model that predicts well spends its effort on the big wiggles, not on the small gap.
- Errors do not cancel. carries the error of both models. If is fitted on few points, its error is large, and all of it lands in .
- Regularization works against the gap. Regularization pulls a model toward simple functions. If is one input among many, "simple" can mean "ignore ", which sets to 0.
A meta-learner is a recipe that turns any regression method (a forest, boosting, a neural network, a kernel smoother) into a CATE estimator. Four common recipes, in words:
- S-learner ("single"): fit one model with as an extra input; then .
- T-learner ("two"): fit on the treated and on the controls; subtract.
- X-learner: first a T-learner. Then impute an effect for every unit with the other group's model, fit a model to these effects, and mix the two effect models.
- DR-learner: build a "doubly robust" pseudo-outcome for every unit (the AIPW term of lesson 05) and regress it on .
Start with the T-learner at 10% treated. Treated and control points come from the same wiggly baseline; the true effect is smooth. The fitted models are drawn in the group colors, and the black curve is the estimate . Notice the false wiggles: the treated model is too smooth to follow the baseline. Switch to X: the wiggles disappear, because the X-learner fits a smooth model to imputed effects. Now pick S and raise the effect size to 3: the estimate is pulled toward 0. Pick DR at 10% treated, then at 50%: the DR-learner is noisy where the propensity is near 0 and good with balanced groups. The readout compares the ATE from with the true ATE and the naive difference in means, which is confounded here because treatment is more likely for large .
The figure shows the main trade-offs. No learner wins everywhere; section 3.2 gives a table.
A gradient-boosting model with strong regularization predicts from . The true effect of is real but small compared with how much varies with . What do you expect for ?
This is the S-learner. The regularized model spends its limited complexity where the loss drops most, which is the large variation in . Splits on give a small gain and are often not made, so . The shrinkage is a bias toward 0, not just extra noise. A T-learner cannot ignore , because it fits separate models.
2.2 Partialling out: residual on residual #
Now take a different question: one number , the effect of on , when many covariates confound it. Linear regression of on and answers it only if the confounding is linear. The Frisch–Waugh–Lovell (FWL) theorem shows another way to compute the coefficient of :
- Predict from and keep the residual : the part of the treatment that does not explain.
- Predict from and keep the residual .
- Regress on . The slope is the effect.
With linear predictions in steps 1 and 2, the slope is exactly the multiple-regression coefficient. Double machine learning replaces the linear predictions by ML models. That is the whole idea.
Step through the four panels. In panel 0 the naive slope of on is about 1.3, far from the true (dashed). Panels 1 and 2 fit and on (black curve). In panel 3, the slope of the residuals with a linear fit is about 1.1: it equals the coefficient of in to all digits (FWL), but it is still biased, because the confounding is curved. Switch to flexible: the residuals lose the curved confounding too, and the slope is close to 0.5.
In the T-learner panel of the first figure, only 10% of units are treated, the baseline is wiggly and the effect is smooth. Which change helps most?
The control model is fitted on 90% of the data and is good. The X-learner computes for each treated unit; these imputed effects are smooth plus noise, so a smooth model fits them well. With it puts weight on this treated-side effect model. The CATE is identified (positivity holds); the problem is estimation, not identification.
3. Definitions and main results #
3.1 The CATE and its identification #
Definition. The conditional average treatment effect (CATE) is . The ATE is its average: .
The CATE is not the individual effect . Two people with the same can react differently; is their average. With richer , gets closer to individual effects, but it never becomes them.
Assumptions (lesson 05, now used for every ):
- Consistency: .
- Conditional exchangeability: (no unmeasured confounding).
- Positivity (overlap): for every we want to evaluate.
Theorem (identification of the CATE). Under 1–3, .
Proof (for ; is the same).
- Positivity gives , so is defined.
- Consistency: .
- Exchangeability: .
- Subtract the same chain for .
Positivity can be checked (look at ). Exchangeability cannot: machine learning does not remove a confounder that is not in . Everything below is about estimation: the estimand is fixed by the theorem, and the methods differ in how well they estimate it.
3.2 Meta-learners #
Let be any regression method ("fit on "). The four learners of section 2, written out:
| Learner | Recipe | Good when | Weak when |
|---|---|---|---|
| S | fit on all data; | effect zero or small; little data | real effect, strong regularization: shrinks to 0 |
| T | fit on treated, on controls; subtract | much data in both groups; very different | one group small; simpler than |
| X | T-learner, then impute effects, fit , mix with | unbalanced groups; smooth | both groups small; poor |
| DR | regress the AIPW pseudo-outcome on (cross-fitted) | good overlap; want robustness | near 0 or 1: huge pseudo-outcomes |
X-learner (Künzel, Sekhon, Bickel and Yu 2019), step by step:
- Fit on the controls and on the treated.
- Impute individual effects. For a treated unit, (observed outcome minus the predicted outcome without treatment). For a control unit, .
- Fit on the treated with target , and on the controls with target .
- Mix: with .
Why this weight? With few treated units ( small), is the better model: it uses the control model , fitted on many points, and its target is the smooth effect plus noise. So the weight on is large. With few controls, the roles swap.
DR-learner (Kennedy 2023). Split the data. On one part, fit . On the other part, compute for each unit the pseudo-outcome
and regress on . Swap the parts and average. Its average over all units is the AIPW estimate of the ATE from lesson 05.
Theorem (the pseudo-outcome is doubly robust). Let be fixed functions (the fitted models, from the other part of the data). Under assumptions 1–3,
So the target of the regression is exactly if , or if both .
Proof
- Given : and . So .
- In the same way, .
- Add and write . For the control part, .
- Subtract: , and by section 3.1.
The error is a product of a propensity error and an outcome-model error. Kennedy (2023) shows that, because of this, the DR-learner can reach the error rate of an "oracle" that regresses the true on , even when the nuisance models converge more slowly. The same product structure is the key to double ML in the next section.
3.3 Double machine learning for one effect #
The model. The partially linear model (Robinson 1988) is
and can be any functions (they carry the confounding). The effect of is the same number for everybody. can be binary or continuous (a dose, a price). Under conditional exchangeability, is the causal effect.
Step 1: Frisch–Waugh–Lovell. Take expectations given : . Subtract this from :
This is Robinson's transformation: the residual of is times the residual of , plus noise. So is the slope of a regression through the origin: , with and . When and are linear projections, this is the FWL theorem.
FWL theorem for linear regression
Let be the matrix of covariates (with a column of ones), the projection onto its column space (linear algebra 03), and . OLS of on gives , with a residual orthogonal to and to every column of .
- Multiply by : , and (because ). So .
- Multiply by : .
- . So .
- and are the residuals of and on . So is the slope of on .
Step 2: replace the projections by ML models. Fit and with any ML method. Both are ordinary prediction problems, so they can be tuned by cross-validation.
Step 3: the DML estimator with cross-fitting (Chernozhukov et al. 2018):
- Split the units at random into folds (often ).
- For each fold : fit and on the other folds, and compute the residuals of the units in fold : , .
- Pool all units:
- The 95% confidence interval is . In practice, repeat with several random splits and report the median.
Why not just plug in an ML model? A natural "plug-in" estimator fits with ML and then regresses on . Its error contains the term : the error of enters directly (first order), multiplied by the confounding . ML models are regularized, so shrinks more slowly than , and this regularization bias dominates the statistical noise. The confidence interval then misses .
Why DML is different: errors multiply. Write the nuisance errors as and . Then and, from Robinson's transformation, . So
- The first term gives the normal distribution of , with standard error of order .
- The middle terms have mean zero if the nuisance models were fitted on other data, because and . This is what cross-fitting buys.
- The last term is the only bias, and it is a product of two errors. If each error is about , the bias is about .
Two views of why DML works. 200 simulations: each run draws a data set from a partially linear model with and computes three estimates, with -nearest-neighbor regression as the ML model. At the outcome model nearly memorises each point: the grey histogram (DML without cross-fitting) shrinks toward 0, but cross-fitting (black) stays centered. Move the slider to or : the outcome model is now too smooth, and the plug-in estimate moves away from 0.5, while DML stays close. The readout also shows how often the 95% CI covers . Errors multiply: exact formulas for a model where both nuisance models are off by ; the plug-in bias grows like , the DML bias like . Simulated in your browser with the model described in the notes of section 3.3.
Neyman orthogonality. The DML estimator solves the moment equation with the score and nuisance . A score is Neyman orthogonal if, at the true values,
In words: a small change in the nuisance functions does not change the moment condition to first order.
Proof that the DML score is orthogonal. Take a direction , functions of .
- Differentiate inside the expectation at : .
- First term: condition on ; . So it is 0.
- Second term: by Robinson's transformation, and .
The plug-in score is not orthogonal: its derivative in the direction is , which is not 0 when is confounded. This is the regularization bias above.
Cross-fitting. If was fitted on unit itself, it has partly learned unit 's noise . Then is correlated with , the middle term no longer has mean zero, and is biased (toward 0 in the figure). Fitting the nuisances on other folds removes this dependence. Cross-fitting does not waste data: every unit is used for the final estimate, and every unit helps fit the nuisance models of the other folds. (This is the same idea as cross-validation: never evaluate a model on the points it was trained on.)
Theorem (DML, informal; Chernozhukov et al. 2018, Theorem 4.1). In the partially linear model, assume , bounded moments, cross-fitting, and nuisance errors (in mean square) that satisfy
Then with , and the interval of step 4 has coverage in large samples.
The rate condition holds, for example, if each nuisance error is : much slower than the of the final estimate. Random forests, boosting and lasso reach such rates under suitable conditions. This is the precise meaning of "two slow errors give one fast estimate".
In the FWL theorem, the coefficient of in the OLS regression of on equals the slope of which regression?
Multiply the fitted regression by , where projects onto the columns of . disappears, the residual stays, and the normal equations give . The slope of on alone is the confounded naive slope (1.3 in the figure, compared with 1.1 for the adjusted coefficient).
You compute DML residuals with nuisance models that were trained on all units, including the unit being predicted. What goes wrong?
Orthogonality is a property of the score and holds either way. The problem is the noise-times-error terms such as : they have mean zero only if does not depend on unit . A model that nearly memorises removes part of from , so the slope shrinks. Cross-fitting predicts unit with a model that never saw it.
3.4 AIPW is double ML for the ATE #
For a binary and heterogeneous effects, the target has the orthogonal score , where is the AIPW pseudo-outcome of section 3.2. The DML recipe gives
with and cross-fitted. This is the AIPW estimator of lesson 05, now with ML models and cross-fitting. The product form of its bias (section 3.2) gives the rate condition for , plus bounded away from 0 and 1. Under it, is asymptotically normal and reaches the smallest possible asymptotic variance (the semiparametric efficiency bound, Hahn 1998). In practice, clip to an interval such as and report how many units were affected.
3.5 Causal trees and causal forests #
A regression tree splits the covariate space into boxes (leaves) and predicts the mean of in each leaf. A causal tree (Athey and Imbens 2016) predicts the effect in each leaf: in a randomized experiment, the difference between the mean outcome of treated and control units in the leaf. Two changes make this work.
1. Split to find different effects. A regression tree chooses the split that most reduces the squared error of . We cannot compute the squared error of . Athey and Imbens show that, up to terms that do not depend on the split and a variance penalty, minimizing the expected squared error of is the same as maximizing . So a good split makes the effects of its two children as different as possible.
2. Honesty. A tree is honest if one subsample chooses the splits and a separate subsample estimates the leaf effects. Why: the split search looks at many candidate splits and picks the one where the two sides look most different. Part of that difference is noise. If the same units then estimate the leaf effects, the noise stays in the estimates: the effects look more extreme than they are, and the usual confidence interval is too narrow. With honesty, the estimation units are fresh. Given the tree, the leaf difference in means is an unbiased estimate of the average effect in that leaf, and the usual interval is valid.
Compare adaptive and honest trees. The left square shows the true effect in four regions; the right square shows the tree's leaves, shaded by the estimated effect. Magenta outlines mark leaves whose 95% CI misses the true average effect of the leaf. Press Run 100 trees at depth 4 in each mode: the adaptive tree's intervals cover the truth only about 75–80% of the time, the honest tree's about 95%. Then compare the MSE at depth 2 and at depth 6: honesty costs accuracy for shallow trees (half the data per task), and it is about equal or slightly better for deep trees.
Causal forests (Wager and Athey 2018) average many honest causal trees, each grown on a random subsample (drawn without replacement) and with random subsets of features at each split: . Under conditions on the subsample size, the leaf sizes and the smoothness of , they prove that is consistent and asymptotically normal at each , with a variance that can be estimated (by the infinitesimal jackknife). So a causal forest gives a confidence interval for , which most ML methods cannot.
Generalized random forests and the R-learner
Forest weights. A forest defines how similar a training point is to a target point : , where is the leaf of tree that contains . The weights are non-negative and add up to 1. A random forest prediction is : an adaptive nearest-neighbor average.
Generalized random forests (Athey, Tibshirani and Wager 2019) use these weights to solve a local
moment equation for any estimating equation . For
the CATE, the grf causal forest first computes out-of-bag nuisance estimates and
("local centering"), then solves the residual-on-residual equation of section 3.3
locally:
So a causal forest is "double ML, solved separately near each , with neighbors chosen by a forest". The same machinery gives quantile forests, instrumental-variable forests and others. Exercise 4 of the notebook builds a small version with scikit-learn.
R-learner (Nie and Wager 2021). Robinson's transformation also holds with a varying effect: if , then . So the true minimizes the R-loss
with cross-fitted and any regularizer . Equivalently: regress the pseudo-outcome on with sample weights , with any ML method that accepts weights. Nie and Wager prove a quasi-oracle property: with nuisance errors of order , has the same error rate as if and were known. The R-loss is also a way to compare CATE models on validation data.
3.6 Evaluating a CATE model without ground truth #
For a prediction model we compute the test error. For a CATE model we cannot: is never observed (the fundamental problem of lesson 02). Four tools, all best used on a randomized held-out set (the propensity is known and there is no confounding):
1. The transformed outcome. With known , define
Theorem. Under assumptions 1–3, .
Proof. and . Subtract and use section 3.1.
So is a noisy but unbiased "label" for the effect. For a model fitted on other data, (the cross term vanishes because ). The second term does not depend on the model. So the mean squared error against ranks models correctly, although its value is much larger than the true error. (The AIPW pseudo-outcome is a lower-variance label of the same kind.)
2. Uplift and Qini curves. Sort the test units by , from high to low. For the top units, compare the treated and control outcomes among them:
where and are the mean outcomes of the treated and control units among the top , and is the number of treated among them. estimates the number of extra successes if we treat these units (the uplift curve); is the Qini curve of Radcliffe (2007), the same quantity counted in the treated group. A good model rises fast; random targeting is the straight line from 0 to ; the area between the curve and that line (the Qini coefficient) summarizes the model. Unlike a churn or response model, the uplift curve measures the effect of targeting.
Choose a budget and a cost. A simulated shop ran a randomized coupon test on 20,000 customers. The oracle sorts by the true effects; the black uplift model is a noisy version of them; the response model sorts by the probability to buy with a coupon. Notice that the response model's curve first goes down: the likely buyers buy anyway, and the coupon slightly lowers the purchases of some of them. Move the budget slider and read the extra purchases. Raise the cost per coupon: the best budget moves left, to the point where the next customer's effect is smaller than the cost. Switch to the weak model to see a flatter curve.
3. Calibration by groups. Sort the test units into, say, 5 groups by . In each group, estimate the average effect (difference in means in an RCT, or the mean of ) and compare it with the mean of in the group. A useful model has group effects that increase from group 1 to group 5 and lie near the predictions. These group average treatment effects (GATES) come with confidence intervals, so the comparison is honest.
4. The best linear predictor test (Chernozhukov, Demirer, Duflo and Fernández-Val). Treat the model's score as a feature. The best linear predictor of from is , with and . Both can be estimated in an RCT by a linear regression of on a constant, and (plus optional baseline controls), with weights . means the model found no heterogeneity that is real; means its scores have the right scale. A test of is a test for heterogeneity.
From effects to decisions. If treating costs (in units of ), the best rule given is "treat if ". The plug-in policy treats if . Its value can be estimated on a randomized test set (lesson 11 does this for general policies). Athey and Wager (2021) learn a policy directly: choose a rule from a simple class (for example, a depth-2 tree) that maximizes the average AIPW score of the actions it takes. This gives rules that are easy to explain and come with regret guarantees.
A team wants to report the mean squared error of their CATE model on last year's customer data, as they do for their churn model. Why is this not possible directly?
For each customer we see the outcome under one treatment only, so the target is missing for everybody (the fundamental problem of causal inference). On a randomized test set, the transformed outcome has , so the MSE against ranks models correctly (its level is shifted by a model-independent constant). Uplift curves and group effects are the other tools. is the label of an outcome model, not of an effect model.
3.7 A practical guide #
- Write the assumptions first. Draw the graph (lessons 03–04). Put only pre-treatment variables in . Causal ML adjusts only for what is in ; it cannot fix a missing confounder (use the sensitivity analysis of lesson 05).
- Check overlap. Plot for treated and controls. With values near 0 or 1, AIPW and the DR-learner become unstable. Clip , restrict the population (and say so: the estimand changes), or use overlap weights.
- Nuisance models. Use strong prediction methods (gradient boosting, random forests, lasso with interactions) and tune them by cross-validation for prediction. For a binary , use a calibrated classifier for .
- Cross-fit with folds; repeat over a few random splits and report the median estimate.
- Report in this order: the ATE (AIPW or DML) with a confidence interval; a test for heterogeneity (BLP, GATES); then the CATE model, its uplift curve on held-out randomized data, and the policy it implies.
- Treat discovered subgroups as hypotheses. A forest searches many splits. Confirm a surprising subgroup on new data, ideally a new experiment.
Answers to section 1. (1) No. The likely buyers may buy without a coupon, so the coupon adds little for them, and for some it can even lower purchases. Targeting should rank by the effect , estimated with an uplift model; the response model curve in the uplift figure shows the loss. (2) is shrunk toward 0: this is the regularization bias of the S-learner (section 2.1). (3) Much smaller. In DML the nuisance errors enter only as a product (section 3.3), so two errors of about give a bias of the order of . A plug-in estimator would carry the error directly.
4. Worked example #
A shop sends a coupon to some customers and measures spending in the next month. The only covariate is : for new customers, for returning customers. Returning customers were more likely to get the coupon. We assume that is the only confounder. The data, as cell sizes and mean spending:
| Cell | mean | |
|---|---|---|
| , coupon () | 20 | 12 |
| , no coupon () | 80 | 10 |
| , coupon | 80 | 26 |
| , no coupon | 20 | 20 |
Step 1: the naive comparison. Mean spending with a coupon: . Without: . Naive difference: . It is confounded: the coupon group is mostly returning customers, who spend more anyway.
Step 2: the CATE (T-learner with cell means). and . The coupon helps returning customers three times as much. With a discrete and one mean per cell, the S- (with an interaction), T-, X- and DR-learners all give these same two numbers; they differ only when models must smooth or extrapolate.
Step 3: ATE and ATT. Both groups have 100 customers, so . The treated are 20 new and 80 returning customers, so .
Step 4: double ML by hand. The nuisance functions are cell averages.
- and .
- and .
Residuals and . Inside a cell, is the same for every unit, so (the individual noise around the cell mean sums to 0):
| Cell | |||||
|---|---|---|---|---|---|
| , | 20 | ||||
| , | 80 | ||||
| , | 80 | ||||
| , | 20 | ||||
| sum |
So . Check with the formula of the warning box in section 3.3: the weights are for both strata, so . Here it equals the ATE because the two strata have the same weight. Check-yourself question 2 changes one number and shows that it does not always.
Step 5: one AIPW pseudo-outcome. A returning customer without a coupon spent . With , , :
One pseudo-outcome is far from the cell effect 6: the weight multiplies the residual by 5. But the residuals of the cell average to 0, so the mean of over the cell is exactly 6. This is why DR-learners need many units, or good overlap, to be stable.
Step 6: an uplift curve with 8 units. A randomized test, units already sorted by from high to low; = coupon, = bought (1) or not (0):
| rank | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | |
| 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
- Top 2: treated , control ; .
- Top 4: , ; .
- Top 6: , ; .
- All 8: , ; .
The curve is : treating the top half gives about 4 extra purchases, treating more adds nothing and then loses. If a coupon costs purchases, the net gain is for the top half and for the top 75%. So we treat the top half. (With 8 units these numbers are very noisy; real uplift curves need thousands of units, as in the figure.)
5. In code #
NumPy and scikit-learn check the worked example and run DML with random forests on simulated data.
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import KFold
# (a) the two-stratum example: cell sizes and cell means of Y
n = {(0, 1): 20, (0, 0): 80, (1, 1): 80, (1, 0): 20} # (X, T): count
ym = {(0, 1): 12., (0, 0): 10., (1, 1): 26., (1, 0): 20.} # (X, T): mean Y
x = np.concatenate([[k[0]] * v for k, v in n.items()])
t = np.concatenate([[k[1]] * v for k, v in n.items()]).astype(float)
dev = np.concatenate([np.resize([-1., 1.], v) for v in n.values()]) # noise that averages to 0 in each cell
y = np.array([ym[(a, int(b))] for a, b in zip(x, t)]) + dev
tau_hat = {s: float(y[(x == s) & (t == 1)].mean() - y[(x == s) & (t == 0)].mean()) for s in (0, 1)}
e_hat = {s: float(t[x == s].mean()) for s in (0, 1)}
print(tau_hat, e_hat) # {0: 2.0, 1: 6.0} {0: 0.2, 1: 0.8}
print(round(y[t == 1].mean() - y[t == 0].mean(), 3)) # 11.2 (naive)
print(np.mean([tau_hat[s] for s in x])) # 4.0 (ATE)
print(np.mean([tau_hat[s] for s in x[t == 1]])) # 5.2 (ATT)
# residual on residual, with the cell averages as nuisance functions
t_res = t - np.array([e_hat[s] for s in x])
l_hat = {s: y[x == s].mean() for s in (0, 1)}
y_res = y - np.array([l_hat[s] for s in x])
print(round(t_res @ y_res, 3), round(t_res @ t_res, 3), round((t_res @ y_res) / (t_res @ t_res), 3))
# 128.0 32.0 4.0
# (b) double ML with random forests and 2-fold cross-fitting on simulated data
rng = np.random.default_rng(0)
N = 2000
X = rng.normal(size=(N, 5))
m = np.tanh(2 * X[:, 0]) + 0.5 * X[:, 1] # E[T | X]
g = 2 * np.tanh(2 * X[:, 0]) + np.sin(2 * X[:, 1]) # effect of X on Y
T = m + rng.normal(size=N)
Y = 0.5 * T + g + rng.normal(size=N) # true theta = 0.5
print(round(np.polyfit(T, Y, 1)[0], 3)) # 1.245 (naive slope, confounded)
l_hat_, m_hat_ = np.zeros(N), np.zeros(N)
for train, test in KFold(2, shuffle=True, random_state=0).split(X):
rf = dict(n_estimators=200, min_samples_leaf=5, random_state=0)
l_hat_[test] = RandomForestRegressor(**rf).fit(X[train], Y[train]).predict(X[test])
m_hat_[test] = RandomForestRegressor(**rf).fit(X[train], T[train]).predict(X[test])
Tt, Yt = T - m_hat_, Y - l_hat_
theta = (Tt @ Yt) / (Tt @ Tt)
se = np.sqrt(np.sum(Tt**2 * (Yt - theta * Tt) ** 2)) / (Tt @ Tt)
print(round(theta, 3), round(se, 3)) # 0.514 0.022
# (c) one AIPW pseudo-outcome: a control unit in stratum X = 1 with Y = 17
mu1, mu0, e = 26., 20., 0.8
print(round(mu1 - mu0 - (17 - mu0) / (1 - e), 3)) # 21.0
# (d) uplift curve of 8 randomized units, already sorted by predicted effect
tt = np.array([1, 0, 1, 0, 1, 0, 1, 0]); yy = np.array([1, 0, 1, 0, 0, 0, 0, 1])
for k in (2, 4, 6, 8):
a, b = tt[:k] == 1, tt[:k] == 0
print(k, float((yy[:k][a].mean() - yy[:k][b].mean()) * k)) # 2 2.0 / 4 4.0 / 6 4.0 / 8 2.0
The DML estimate has a 95% interval of about , which contains the true ; the naive slope is far off. The notebook adds the plug-in estimator, repeats the experiment over many seeds, and builds the meta-learners, a small causal forest and an uplift curve.
6. Where it shows up #
- Uplift modeling and targeting. Coupons, retention offers, notifications and ads are sent to the customers with the largest estimated effect, not the largest purchase or churn probability. Models are trained on randomized campaigns and evaluated with Qini curves.
- Heterogeneous effects in A/B tests. Large online experiments report the ATE and then look for segments (new vs returning users, device, country) where the effect differs, with causal forests or the BLP/GATES tests, and with care about multiple testing.
- Medicine. Causal forests and DR-learners on trial or registry data estimate which patients benefit most from a treatment, and which ones carry risk without benefit.
- Economics and policy. DML is standard for effects with many controls: the original paper estimates the effect of 401(k) eligibility on savings; later work uses it for price elasticities and labour-market programs. Causal forests target job-training and welfare programs.
- Machine learning for science. In agriculture and ecology, the effect of an intervention (fertilizer, irrigation, a conservation policy) depends on soil, weather and location; causal forests map where it helps. In climate and Earth science, DML-style partialling out is used to separate the effect of one driver from many correlated background variables.
7. Common mistakes #
- Targeting with a response or churn model. It ranks by the outcome, not by the effect. The people most likely to buy or to stay are often the ones the treatment changes least. Use an uplift model and check it with an uplift curve on randomized data.
- Reading the effect from an S-learner with strong regularization. The model can ignore , and shrinks toward 0. Compare with a T-, X- or DR-learner, and check that is actually used.
- No cross-fitting. Residuals from nuisance models that saw the same units are too small and correlated with the noise: biased and too narrow intervals. Always predict each unit with a model trained on other folds.
- "ML handles confounding." DML and causal forests adjust only for the measured . An unmeasured confounder biases them as much as it biases regression. Use domain knowledge and a sensitivity analysis (lesson 05).
- Many features, including bad controls. Putting post-treatment variables (mediators, colliders) into "because the model can handle it" breaks identification (lessons 03–04). Only pre-treatment covariates belong in .
- Reporting the partially linear as the ATE when effects vary. It is an overlap-weighted average (section 3.3). For the ATE use AIPW.
- Ignoring overlap. With near 0 or 1, pseudo-outcomes explode. Check the histogram of , and clip or restrict, saying how the estimand changes.
- Evaluating a CATE model in-sample, or with as the label. Use a held-out randomized set, the transformed outcome, uplift curves and group effects.
8. Check yourself #
- In an X-learner, at some : , , . Compute
, and say why the X-learner trusts more here.
Answer
. Only 10% of units like this are treated. uses the imputed effects of the treated, where is fitted on the large control group and is accurate. uses , which is fitted on few points and is less accurate. - Change the worked example: among returning customers, 50 get the coupon (mean spending 26) and 50 do
not (mean 20). Nothing else changes. What do the ATE and the partially linear DML estimate become?
Answer
The CATEs stay and , so the ATE stays . Now , so the weights are for new and for returning customers: . The partially linear estimate gives more weight to the stratum where the treatment varies more. It is not the ATE when effects differ. - In an RCT with , compute the transformed outcome for a treated unit with , a
treated unit with and a control unit with . Why can single values of be far from
any plausible effect?
Answer
: treated with gives ; treated with gives ; control with gives . Each uses one outcome only, so it is very noisy. Only its conditional mean equals . That is why it ranks models correctly on average but its MSE level is large. - Does cross-fitting with folds mean that the final estimate uses only one fifth of the data?
Answer
No. Every unit gets residuals from models trained on the other four folds, and pools all units. Every unit is also used to train the nuisance models for the other folds. The only cost is that each nuisance model is trained on of the data. - At depth 2, the honest tree in the figure has a larger MSE than the adaptive tree; at depth 6, a
smaller one. Explain both.
Answer
Honest trees use half the units to choose splits and half to estimate effects, so each part is noisier: at depth 2 this loss dominates. Deep adaptive trees choose many splits on noise and then estimate the leaves on the same noise, so their leaf effects are too extreme; this overfitting dominates at depth 6. Coverage is the clearer difference: about 95% for honest leaves, about 75–80% for adaptive leaves. - A DML analysis with random forests gives (SE ); OLS of on and gives
. Which assumptions must hold before you call the causal effect?
Answer
No unmeasured confounding given (conditional exchangeability), only pre-treatment covariates in , consistency, and enough variation of given (overlap, ). The partially linear form must hold, or must be read as the weighted average . The nuisance models must be good enough for the rate condition. The difference from OLS suggests nonlinear confounding that OLS missed.
Define the CATE and say when it equals .
. It equals under consistency, conditional exchangeability given , and positivity .
Why does a regularized S-learner tend to underestimate effects?
is one input among many; regularization lets the model ignore it when the effect is small compared with the variation in , so is pulled toward 0.
How does the X-learner combine its two effect models?
. With few treated units it trusts , which is built from the accurate control model.
Write the DML estimator for the partially linear model.
, with , , and cross-fitted ML predictions of and from .
What is Neyman orthogonality, in words?
The derivative of the moment condition with respect to the nuisance functions is zero at the truth, so small nuisance errors change the estimate only through products of errors (second order).
What does cross-fitting prevent?
Overfitting bias: a nuisance model that saw unit partly fits 's noise, which correlates its residuals with the errors. Predicting each unit with a model trained on other folds removes this.
State the rate condition for DML in the partially linear model.
; for example, each nuisance error is .
What makes a causal tree "honest", and what does it buy?
Different units choose the splits and estimate the leaf effects. The leaf estimates are then not fitted to their own noise, so the usual confidence intervals are valid.
In an RCT with known , what is the transformed outcome and its key property?
, with .
What does an uplift curve show?
For each share of units sorted by , the estimated number of extra successes if we treat that top share: , computed on randomized data.
9. Interview angle #
- "How would you decide which users get a discount?" — Not by purchase or churn probability. Run a randomized campaign (or use logged data with all confounders measured), estimate the CATE with an uplift model (X-/DR-learner, causal forest), evaluate it with an uplift/Qini curve on a randomized holdout, and treat users with above the cost of the discount.
- "What is double ML, and why cross-fit?" — Partial out from and with ML models and regress residual on residual. The score is Neyman orthogonal, so nuisance errors enter as a product and the estimate is -consistent with a valid CI. Cross-fitting stops the nuisance models from fitting the noise of the units they are evaluated on.
- "S-, T- or X-learner?" — S if the effect is small and data scarce (but it shrinks effects); T with plenty of data in both arms; X when the arms are unbalanced; DR or R when overlap is good and you want robustness and fast rates.
- "How do you evaluate a CATE model if you never see individual effects?" — On a randomized holdout: uplift/Qini curves, calibration by groups (GATES), the BLP test, MSE against the transformed outcome for ranking models.
- "Why are causal forests honest?" — To avoid choosing splits and estimating effects on the same noise; it makes leaf estimates unbiased given the tree and gives valid confidence intervals.
10. Practice #
The notebook for this lesson has five exercises, each with a check cell and a folded solution:
- Simulate data with a known and build the S-, T- and X-learners with scikit-learn; compare their error against the truth with 10% and 50% treated.
- Write
dml_plrwith -fold cross-fitting and a standard error; compare the plug-in estimator, DML without cross-fitting and DML with cross-fitting over many seeds (bias and coverage). - Build the DR-learner from cross-fitted AIPW pseudo-outcomes and check its ATE against the truth.
- Build a small honest causal forest: a random forest on one half gives the neighborhoods, and a weighted residual-on-residual regression on the other half gives .
- Compute an uplift curve on a simulated randomized test set and choose the best budget for a given cost per treatment.
11. Watch and read #
- Chernozhukov, Hansen, Kallus, Spindler and Syrgkanis, Applied Causal Inference Powered by ML and AI (free): chapters 4 and 10 (orthogonality and double ML), 14–15 (heterogeneous effects, meta-learners, model evaluation).
- Stefan Wager, Causal Inference: A Statistical Learning Approach (free PDF): chapter 3 (doubly robust methods, debiased ML), chapter 4 (heterogeneous effects, R-learner), chapter 5 (policy learning).
- Chernozhukov et al. (2018), Double/debiased machine learning for treatment and structural parameters.
- Künzel, Sekhon, Bickel and Yu (2019), Meta-learners for estimating heterogeneous treatment effects using machine learning.
- Kennedy (2023), Towards optimal doubly robust estimation of heterogeneous causal effects.
- Nie and Wager (2021), Quasi-oracle estimation of heterogeneous treatment effects (the R-learner).
- Athey and Imbens (2016), Recursive partitioning for heterogeneous causal effects (honest causal trees).
- Wager and Athey (2018), Estimation and inference of heterogeneous treatment effects using random forests; Athey, Tibshirani and Wager (2019), Generalized random forests.
- Chernozhukov, Demirer, Duflo and Fernández-Val, Generic machine learning inference on heterogeneous treatment effects in randomized experiments (BLP and GATES).
- Matheus Facure, Causal Inference for the Brave and True, part II: meta-learners, debiased ML and evaluation of CATE models, with Python code.
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.