前置条件与学习依赖 / PREREQUISITES
① 数学 / 统计基础
随机森林/决策树原理、bootstrap、out-of-bag 估计、$\sqrt{n}$ 推断;已学 16 DML
② 经济学理论前置
能说出"政策效应应当沿哪些维度分化",用于解释 CATE 异质性的经济学含义。
③ 软件 / 计算前置
R 4.1+:install.packages("grf");Python:pip install econml scikit-learn
④ 站内前置页面
10 异质性分析(传统做法对比);16 DML
⑤ 难度分级
前沿进阶

01 从 ATE 到 HTE / CATE

ATE 回答"政策平均影响多大",但政策制定者更关心:谁受影响最大?应该把资源优先给谁?这就需要刻画效应的异质性处理效应(Heterogeneous Treatment Effect, HTE),更具体地,条件平均处理效应:

Equation (1) — CATE 定义
$$\tau(x)=E\big[Y(1)-Y(0)\mid X=x\big]$$

$\tau(x)$ 是一个函数:给定协变量 $X=x$ 的子人群,处理效应的平均值。传统做法是研究者事先指定几个 $X$ 维度,做交互项或分样本回归(见 10 异质性分析)。这种做法的局限是:(1) 只能探索你想到的维度;(2) 高维协变量下手工交互项组合爆炸;(3) 多重检验下容易 p-hacking。因果森林的目标就是让数据自己告诉你 $\tau(x)$ 的形状

📌 三种异质性视角

(1) ATE:$\tau$ 是常数;(2) 线性异质性:$\tau(x)=\theta_0+\theta_1'x$(DML 的 IRM 模型);(3) 任意形状异质性:$\tau(x)$ 是任意函数(因果森林 / GFR)。越往后越灵活,但估计方差越大。

02 因果森林原理与诚实树

因果森林(Wager & Athey 2018; Athey, Tibshirani & Wager 2019)是随机森林的改造版。普通决策树在叶子节点预测 $Y$;因果树在叶子节点估计处理效应 $\hat\tau_\ell$(叶子 $\ell$ 内处理组与对照组的均值差)。递归分裂的目标不是最小化 $Y$ 的预测误差,而是最大化叶子节点之间的效应差异

但这种做法有一个统计陷阱:如果用同一批数据既"选择分裂点"又"在叶子里估计 $\tau_\ell$",那么分裂会偏向于"噪声看起来差异很大"的位置,导致估计的 $\tau(x)$ 有偏、置信区间不覆盖。诚实树(honest tree)解决这个问题:

Step 1 · 把每个样本的一半数据(J1)用于"选择分裂点"
只在 J1 上递归生长,决定每个叶子的边界。
Step 2 · 把另一半数据(J2)用于"估计叶子内 $\tau_\ell$"
在固定好的叶子里,用 J2 数据估计处理组与对照组的均值差。
Step 3 · 装袋成森林
对 bootstrap 样本重复 Step 1-2,把所有树的预测平均,得到 $\hat\tau(x)$。

诚实性把"模型选择"和"效应估计"用不同样本分开,从而消除了过拟合。grf 包的默认参数 honesty=TRUE, honesty.fraction=0.5 就是这个机制。

分裂准则也和普通随机森林不同。普通树按"叶子内 $Y$ 的方差下降"分裂;因果树按"叶子之间的处理效应差异"分裂——具体地,对每个候选分裂点,计算左右两个子叶子的 $\hat\tau_\ell$ 之差,取最大化这个差异(同时要求每个叶子内处理组和对照组都有足够样本)的分裂点。这等价于一个"因果 R 平方"目标:我们要找的不是"最能预测 $Y$ 的分割",而是"最能区分效应的分割"。这是因果森林与预测随机森林最本质的算法差异。

另一个工程细节:ci.group.size。为了估计方差,grf 把树再分组,组内的树用不同的样本子集拟合,组间差异用来度量估计的不确定性。ci.group.size=2 是默认,正式研究建议设为 3 或 4 以获得更稳的方差估计。

03 渐近正态性与置信区间

Wager & Athey (2018) 的核心理论贡献是:在诚实树 + 适当正则化(叶子大小、分裂规则)下,$\sqrt{n}\big(\hat\tau(x)-\tau(x)\big)$ 渐近正态,且方差可估。grf 包通过 estimate.variance=TRUE 给出每一个预测点 $\hat\tau(x)$ 的置信区间。这在机器学习方法里非常罕见——多数 ML 只能给点估计,因果森林能给带置信区间的 CATE

✅ 解释 $\hat\tau(x)$ 的正确姿势

不要只看 $\hat\tau(x)$ 的点估计;要看它的置信区间宽度。如果 CI 跨过零,说明在这个 $x$ 处效应不显著异于零。报告时画"CATE 直方图"和"CATE 沿某 $X$ 变量的散点 + CI"。

04 R 完整代码:grf 包

R · grf 因果森林完整示例
# ============================================================
# 04.1 R: 用 grf 估计 CATE、变量重要性、置信区间
# install.packages("grf")
# ============================================================
library(grf)
set.seed(123)

# ---- 1. 模拟数据:n=2000, p=6;CATE 与 X1, X3 有关 ----
n <- 2000
p <- 6
X <- matrix(rnorm(n * p), n, p)
W <- rbinom(n, 1, 0.5)                                   # 随机分配处理
# 真实 CATE(x) = X[,1] + X[,3](其他变量不影响效应)
tau_true <- X[, 1] + X[, 3]
Y <- tau_true * W + X[, 2] + pmin(X[, 4], 0) + rnorm(n)

# ---- 2. 拟合因果森林(默认 honesty=TRUE)----
cf <- causal_forest(
  X = X,
  Y = Y,
  W = W,
  num.trees = 2000,          # 树数
  min.node.size = 5,         # 叶子最小样本
  honesty = TRUE,            # 诚实树
  honesty.fraction = 0.5,    # 一半选分裂、一半估效应
  ci.group.size = 2          # 用于方差估计
)

# ---- 3. 用 out-of-bag 预测训练样本的 CATE ----
tau.hat.oob <- predict(cf)
hist(tau.hat.oob$predictions,
     main = "OOB CATE 估计分布", xlab = "tau_hat(x)")

# ---- 4. 置信区间(在测试样本上)----
X.test <- matrix(rnorm(100 * p), 100, p)
tau.test <- predict(cf, X.test, estimate.variance = TRUE)
# tau.test$predictions       : CATE 点估计
# tau.test$variance.estimates: 方差估计
# 95% CI = predictions ± 1.96 * sqrt(variance.estimates)
ci_lower <- tau.test$predictions - 1.96 * sqrt(tau.test$variance.estimates)
ci_upper <- tau.test$predictions + 1.96 * sqrt(tau.test$variance.estimates)

# ---- 5. 模型校准诊断(calibration test)----
test_calibration(cf)
# 输出:估计 ATE、最优线性投影 R^2、是否校准良好

# ---- 6. 变量重要性(哪些 X 决定了 CATE)----
varimp <- variable_importance(cf)
print(data.frame(variable = paste0("X", 1:p),
                 importance = round(varimp, 3)))
# X1, X3 的 importance 应显著高于 X2, X4, X5, X6

# ---- 7. 平均处理效应 ATE ----
ate_cf <- average_treatment_effect(cf)
print(ate_cf)   # 估计 ATE 与标准误
R · 用因果森林做政策树(policy tree)
# ============================================================
# 04.2 R: 用 policy_tree 从 CATE 到最优政策
# ============================================================
library(grf)

# 用上一步的 cf
# 政策树:直接在观察数据上学习"哪些 x 应被处理"
pt <- policy_tree(X, Y, W,
                  depth = 2,             # 树深
                  policy = "overall")    # 最大化整体福利

# 在测试样本上预测政策:1=建议处理, 0=建议不处理
policy.predict <- predict(pt, X.test)
table(policy.predict$predictions)

# 画政策树
plot(pt)
# 树的每个叶子给出"按哪个变量切分 -> 该叶子里是否建议处理"
# 这就是可解释的"政策规则"

05 Python 完整代码:econml CausalForestDML

Python · econml CausalForestDML 完整示例
# ============================================================
# 05.1 Python: econml CausalForestDML
# pip install econml scikit-learn
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import GradientBoostingRegressor, GradientBoostingClassifier
from econml.dml import CausalForestDML

np.random.seed(42)

# ---- 1. 模拟数据(与 R 版相同)----
n, p = 2000, 6
X = np.random.normal(size=(n, p))
W = np.random.binomial(1, 0.5, size=n)
tau_true = X[:, 0] + X[:, 2]            # 真实 CATE(x)
Y = tau_true * W + X[:, 1] + np.minimum(X[:, 3], 0) + np.random.normal(size=n)

# ---- 2. 拟合 CausalForestDML ----
est = CausalForestDML(
    model_y=GradientBoostingRegressor(n_estimators=200, max_depth=3,
                                      random_state=42),
    model_t=GradientBoostingClassifier(n_estimators=200, max_depth=3,
                                       random_state=42),
    discrete_treatment=True,              # W 是二值
    n_estimators=1000,                    # 树数
    min_samples_leaf=20,
    max_samples=0.5,
    honest=True,                          # 诚实分裂
    inference=True,                       # 启用置信区间
    random_state=42,
)
est.fit(Y, W, X=X)

# ---- 3. CATE 点估计与置信区间 ----
cate_hat = est.effect(X)                  # 每个个体的 CATE
lb, ub = est.effect_interval(X, alpha=0.05)

print("CATE 均值 =", cate_hat.mean())
print("CATE 标准差 =", cate_hat.std())
print("95% CI 半宽 均值 =", ((ub - lb) / 2).mean())

# ---- 4. 与真实 CATE 对比 ----
plt.figure(figsize=(6, 6))
plt.scatter(tau_true, cate_hat, alpha=0.5, s=10)
plt.plot([-4, 4], [-4, 4], "r--")
plt.xlabel("true CATE"); plt.ylabel("estimated CATE")
plt.title("Causal Forest: true vs estimated CATE")
plt.tight_layout()
plt.savefig("cate_true_vs_hat.png", dpi=120)

# ---- 5. 变量重要性(基于分裂频率)----
imp = est.feature_importances_
for i in range(p):
    print(f"X{i+1}: importance = {imp[i]:.3f}")
# X1, X3 应最高

# ---- 6. 政策解释:用单棵决策树逼近 CATE ----
from econml.cate_interpreter import SingleTreeCateInterpreter
interp = SingleTreeCateInterpreter(include_model_uncertainty=True,
                                   max_depth=2)
interp.interpret(est, X)
# interp.plot()  # 在 Jupyter 中画可解释的 CATE 树

06 政策树 Policy Tree 与靶向

从"估计 $\tau(x)$"到"做出政策决策",Athey & Wager (2021, Operations Research) 提出政策树(Policy Tree):直接优化"给定预算下,把政策分配给谁,期望福利最大"。与 CATE 估计不同,政策树的目标不是让 $\hat\tau(x)$ 点估计准,而是让分配规则 $D^*(x)\in\{0,1\}$ 最大化 $\mathbb{E}[\tau(x)\cdot D^*(x)]$。

实务流程:

  1. 用因果森林估计 $\hat\tau(x)$ 与置信区间。
  2. 按 $\hat\tau(x)$ 排序,把政策资源优先分给 $\hat\tau(x)$ 最高的 $q\%$ 人群——这就是靶向(targeting)
  3. 用政策树把"哪些人群该被处理"压缩成一条可解释的规则("X1 > 0.5 且 X3 > 0 时处理")。
  4. 在留出样本或 RCT 数据上验证政策树的期望收益是否显著优于"全民处理"或"随机处理"。
⚠️ 靶向的伦理与统计边界

政策靶向可能把资源从"最贫困"转移到"对政策最敏感"的人群。Haushofer et al. (2025, AER) 标题就叫"Targeting Impact versus Deprivation",明确讨论按效应靶向 vs 按贫困靶向的权衡。统计上,靶向规则的估计本身需要诚实样本,否则会过拟合到训练数据的噪声。

07 与传统交互项 / 分样本回归对比

方法异质性来源可识别的形状置信区间主要风险
分样本回归研究者预先切分离散的、低维有(但忽略了切分本身)p-hacking、未校正多重检验
交互项 $D\times X$研究者指定调节变量线性异质性只能探索想到的维度
分位数回归沿 $Y$ 分布的异质性分布形状不是 $X$ 维度的异质性
DML-IRM线性异质性 $\theta(X)$线性有(半参有效)形状受限
因果森林数据驱动任意非参数有(渐近正态)需要大样本、外推风险

实务建议:把因果森林当作"发现工具",把传统交互项当作"确认工具"。先用因果森林发现"效应沿哪些 $X$ 维度分化",再用交互项在同一数据集(或新数据)上正式检验,避免"用同一数据发现又确认"的过拟合。

从写作角度,一份合格的因果森林章节通常包含四张图/表:(1) CATE 直方图,展示 $\hat\tau(x)$ 的分布形状——是集中在零附近(几乎没有异质性),还是两端有长尾(异质性很大);(2) CATE 沿关键协变量的散点图,横轴是某个连续 $X$,纵轴是 $\hat\tau(x)$,叠加核密度或低阶多项式拟合;(3) 变量重要性表,列出 Top 5-10 个驱动 CATE 的变量,并解释经济学含义;(4) 政策树图或靶向人群特征表,说明"建议处理"与"不建议处理"两组在 $X$ 上的差异。

还要特别说明 CATE 与 ATE 的关系:CATE 的加权平均就是 ATE。如果因果森林给出的 ATE 与 DML / OLS 估的 ATE 差很多,说明森林本身拟合有问题(过拟合、honesty 未开、样本量不足),必须先排查再继续解释异质性。

因果森林与 BART / 其他异质性方法

除了因果森林,估计 $\tau(x)$ 还有两条常见路线:(1) BART(Bayesian Additive Regression Trees),用贝叶斯树的后验分布给出 CATE 的后验区间,天然带不确定性;(2) S-/T-/X-/R-learner 等元学习器(meta-learner),把任意预测模型包装成 CATE 估计器。因果森林的优势是渐近正态性严格、grf/econml 包成熟;BART 的优势是后验分布自然、小样本稳;X-learner 在处理组与对照组样本严重不平衡时表现更好。实务中,Athey-Wager 团队的 grf 仍然是经济学顶刊的主流选择,因为它和 DML 同一学派、理论保证最清晰。

从"估计异质性"到"写论文",还有一个容易被忽略的环节:异质性发现的多重检验问题。当你把 20 个协变量都扔进因果森林,森林总会"找到"一些异质性——哪怕真实 DGP 里根本没有。这是因为 ML 的优化目标就是最小化训练误差,它会把噪声也当成信号。缓解办法:(1) 报告 CATE 的整体 $R^2$(grf 的 test_calibration 给出),若接近零则说明几乎没有真异质性;(2) 用独立的留出样本验证 $\hat\tau$ 的排序是否稳定;(3) 在论文里诚实说明"这是数据驱动的探索性分析,需要外部样本复制"。

应用论文精读:Delfino (2024) 与 Haushofer et al. (2025)

Delfino (2024, AER) 研究"鼓励男性进入传统粉色职业(如护士、幼儿教师)"的现场实验。她把招聘广告随机分配给男性求职者,有的广告强调"欢迎男性申请",有的没有。传统的 ATE 分析给出平均处理效应;进一步用因果森林探索异质性,发现效应集中在"对性别刻板印象敏感度低、家庭中有女性从事类似职业"的子人群。这种"RCT + 因果森林 + 子群体机制讨论"的写法,已经成为 AER 上实验论文的标准结构。

Haushofer et al. (2025, AER) 研究肯尼亚现金转移支付的靶向问题。传统做法是按"贫困程度"选受益人;论文提出另一种思路:按"预期效应大小"选受益人。他们用因果森林估计每个家庭的 CATE,比较两种靶向规则下的总福利。核心发现是:按效应靶向 vs 按贫困靶向各有优劣——按贫困靶向帮到最需要的人,但按效应靶向总福利更大。这篇论文把"政策学习"从统计学概念真正带进了发展经济学的政策讨论。

从因果森林到政策建议的写作模板

在论文中报告因果森林结果时,建议按以下顺序:(1) 先报告 ATE 与传统异质性(交互项 / 分样本);(2) 报告因果森林的校准诊断($R^2$、CI 覆盖率);(3) 画 CATE 直方图与变量重要性;(4) 用政策树给出"可执行"的靶向规则;(5) 在外部样本或 bootstrap 上验证政策规则的稳定性;(6) 讨论靶向的伦理与公平含义(如 Haushofer et al. 做的)。这个结构既能让计量审稿人满意,也能让政策读者看懂"你到底建议怎么做"。

最后提醒:因果森林不是"自动发现因果"的黑箱。它仍然需要你先回答上一节 DAG 框架里的问题——处理 $D$ 与结果 $Y$ 之间的后门路径是否被 $X$ 阻断?如果答案是否定的,因果森林给出的 $\hat\tau(x)$ 仍然是有偏的。把因果森林放在"可忽略性成立前提下,非参数地刻画异质性"的位置,而不是"绕过识别假设"的捷径。

08 逐步流程

Step 1 · 估计 ATE 作为基准
先用 DML 或 OLS 估 ATE,确认平均效应存在,再探索异质性。
Step 2 · 拟合因果森林
在 R grf 或 Python econml 中启用 honesty、足够树数(≥2000)、ci.group.size≥2。
Step 3 · 诊断校准
test_calibration() 或 econml 内置诊断,确认 $\hat\tau$ 校准良好;若 R² 接近 0,说明数据里几乎没有异质性。
Step 4 · 报告 CATE 分布与变量重要性
画 CATE 直方图、CATE 沿关键 $X$ 的散点 + CI;列出 Top 重要性变量。
Step 5 · 政策树 / 靶向分析
用 policy_tree 或按 $\hat\tau$ 排序做靶向,在留出样本验证期望福利。
Step 6 · 与传统方法并列报告
把因果森林结果与交互项 / 分样本回归并列,让审稿人看到两边一致。

09 论文案例

English · JASA
Recursive Partitioning for Heterogeneous Causal Effects
Susan Athey & Guido Imbens · Journal of the American Statistical Association, 2016
提出"诚实树"(honest tree)概念:把样本分成"选分裂"和"估效应"两半,第一次让因果树有了有效的置信区间。是因果森林的思想源头。
English · JASA
Estimation and Inference of Heterogeneous Treatment Effects Using Random Forests
Stefan Wager & Susan Athey · Journal of the American Statistical Association, 2018
证明因果森林在诚实分裂下 $\sqrt{n}$ 渐近正态、方差可估。是 grf 包 causal_forest() 的理论出处。
English · PNAS
Generalized Random Forests
Susan Athey, Julie Tibshirani & Stefan Wager · Proceedings of the National Academy of Sciences, 2019
把随机森林推广为一个通用框架:任意低维目标函数(不仅是 CATE,还包括分位数、工具变量效应)都能用"局部核 + 似然"估计。grf 包是其官方实现。
English · Operations Research
Policy Learning with Observational Data
Susan Athey & Stefan Wager · Operations Research, 2021
政策树的方法学论文。给出观察数据下最优政策树的半参效率界与诚实分裂规则。R 包 grf::policy_tree() 即实现此文算法。
English · American Economic Review
Breaking Gender Barriers: Experimental Evidence on Men in Pink-Collar Jobs
Alexia Delfino · American Economic Review, 2024, 114(6): 1816–1853
AER 2024 年现场实验论文。在随机实验数据上用因果森林类方法探索"鼓励男性进入粉色职业"的处理效应异质性,示范了"RCT + 因果森林 + 政策靶向"的现代应用范式。
English · American Economic Review
Targeting Impact versus Deprivation
Johannes Haushofer, Paul Niehaus, Carlos Paramo, Edward Miguel & Michael Walker · American Economic Review, 2025, 115(6): 1936–1974
讨论现金转移支付中"按预期效应靶向"与"按贫困程度靶向"的权衡。用机器学习方法估计 CATE 并比较两种靶向规则的福利结果,是政策学习在发展经济学的代表作。
English · NBER / Applied
Generic Machine Learning Inference on Heterogeneous Treatment Effects in Randomized Experiments
Chernozhukov, Demirer, Duflo & Fernandez-Val · NBER WP 24678(后发于 Annals of Applied Statistics, 2018)
在 RCT 数据上用 ML 估计异质性效应的方法学论文。与因果森林互补,强调"在实验数据上用 ML 发现 HTE"的可行性。

10 常见错误

❌ 错误 1:不开诚实分裂(honesty=FALSE)就报告 CI

不开 honesty 等于用同一批数据既选分裂又估效应,置信区间严重偏窄、覆盖率失真。grf 与 econml 默认 honesty=TRUE,不要关掉。

❌ 错误 2:样本量不足却做高维 CATE

因果森林每个叶子需要足够的处理组和对照组样本。$n=200$、$p=50$ 时,CATE 估计噪声极大。经验法则:$n$ 至少上千、$p$ 不超过 $n/10$;样本小就用线性 DML。

⚠️ 错误 3:外推(extrapolation)到支持域之外

因果森林在数据稀疏区域(X 取值极端)的预测是外推,不可信。报告 CATE 时叠加 $X$ 的核密度,只在"有足够样本支撑"的区域下结论。

⚠️ 错误 4:把 $\hat\tau(x)$ 的排序当成"政策靶向"而不做留出验证

训练样本上 $\hat\tau$ 高的人,在新数据上不一定真是高效应组。政策靶向必须在留出样本或新实验上验证期望福利。

⚠️ 错误 5:把因果森林当"银弹",不报告 ATE 与传统异质性结果

因果森林是补充工具,不是替代。论文应同时报告 OLS ATE、交互项异质性、因果森林 CATE,三者一致才有说服力。

⚠️ 错误 6:忽略未观测混淆

因果森林在可忽略性假设下识别 CATE。它不能解决未观测混淆——如果原始 DGP 有 IV 或 RDD 依赖,应该用 IV-LASSO / 工具变量森林,而不是普通因果森林。

进阶资料

  • grf 官方文档:grf-labs.github.io/grf,含大量案例。
  • econml 文档:econml.readthedocs.io,含 CausalForestDMLSingleTreeCateInterpreter
  • Athey & Imbens (2019), Annual Review of Economics "Machine Learning Methods that Economists Should Know About" —— 综述。
  • Chernozhukov et al. (2018 JEL / Annu. Rev. Econ.) 综述,与 DML 配套阅读。