因果推断资源专题¶
从"X 和 Y 同时发生"到"X 导致 Y"——完整方法论 + 资源索引
🧭 学习路径¶
| 阶段 | 核心内容 | 时间 | 前置 |
|---|---|---|---|
| 🟢 入门 | 相关≠因果、辛普森悖论、反事实思维 | 1 周 | 基础统计 |
| 🟡 核心 | DID、IV、RDD、PSM 的原理与实现 | 3-4 周 | 回归分析 |
| 🟠 进阶 | DAG、do-calculus、结构因果模型 | 4-6 周 | 概率论 |
| 🔴 实战 | DoWhy、EconML、CausalML 工具链 | 持续 | 上述全部 |
🎯 方法选择速查¶
| 我能做什么? | 推荐方法 | Python 工具 | 难度 |
|---|---|---|---|
| 随机分配 | A/B 测试(RCT) | scipy.stats | ⭐⭐ |
| 有前后对照 | 双重差分(DID) | linearmodels | ⭐⭐⭐ |
| 找到工具变量 | 工具变量(IV/2SLS) | linearmodels | ⭐⭐⭐⭐ |
| 有断点阈值 | 断点回归(RDD) | rdrobust | ⭐⭐⭐⭐ |
| 只有观测数据 | 倾向得分匹配(PSM) | causalinference | ⭐⭐⭐ |
| 复杂因果图 | Do-calculus | DoWhy | ⭐⭐⭐⭐⭐ |
| 异质性效应 | Causal Forest / DML | EconML | ⭐⭐⭐⭐ |
详细代码示例见 因果推断实操指南
📚 概述¶
因果推断是数据科学的核心能力之一,用于回答"如果...会怎样"的问题。与相关性分析不同,因果推断能够识别变量之间的因果关系,为决策提供可靠依据。
核心问题: - X 是否导致 Y? - 干预 A 比干预 B 效果好多少? - 如果没有这个政策,结果会怎样?
🎯 核心概念¶
因果推断的三大框架¶
graph TB
A[因果推断] --> B[反事实框架<br>Rubin Causal Model]
A --> C[因果图框架<br>Pearl's DAGs]
A --> D[结构因果模型<br>SCM]
B --> B1[潜在结果]
B --> B2[ATE/ATT]
B --> B3[选择偏差]
C --> C1[有向无环图]
C --> C2[do-算子]
C --> C3[前门/后门准则]
D --> D1[结构方程]
D --> D2[工具变量]
D --> D3[中介分析]
📖 经典书籍¶
入门级¶
| 书名 | 作者 | 年份 | 难度 | 特点 |
|---|---|---|---|---|
| 《The Book of Why》 | Judea Pearl | 2018 | ⭐⭐ | 因果科学科普,无需数学基础 |
| 《Causal Inference in Statistics: A Primer》 | Judea Pearl | 2016 | ⭐⭐⭐ | 因果图入门,含 R 代码 |
| 《Mostly Harmless Econometrics》 | Angrist & Pischke | 2008 | ⭐⭐⭐⭐ | 计量经济学视角,幽默风趣 |
| 《因果推断:实用指南》 | 张杰等 | 2022 | ⭐⭐⭐ | 中文入门,案例丰富 |
进阶级¶
| 书名 | 作者 | 年份 | 难度 | 特点 |
|---|---|---|---|---|
| 《Causal Inference: What If》 | Hernán & Robins | 2020 | ⭐⭐⭐⭐ | 反事实框架标准教材,免费在线 |
| 《Causal Inference in Econometrics》 | Angrist & Pischke | 2014 | ⭐⭐⭐⭐ | 计量经济学方法 |
| 《Counterfactuals and Causal Inference》 | Morgan & Winship | 2014 | ⭐⭐⭐⭐ | 社会科学应用 |
高级级¶
| 书名 | 作者 | 年份 | 难度 | 特点 |
|---|---|---|---|---|
| 《Causality》 | Judea Pearl | 2009 | ⭐⭐⭐⭐⭐ | 因果图理论圣经 |
| 《Elements of Causal Inference》 | Peters, Janzing, Schölkopf | 2017 | ⭐⭐⭐⭐⭐ | 机器学习视角 |
| 《Causal Inference and Discovery in Python》 | Aleksander Molak | 2022 | ⭐⭐⭐⭐ | Python 实战 |
🎓 在线课程¶
免费课程¶
| 课程 | 平台 | 机构 | 时长 | 链接 |
|---|---|---|---|---|
| Causal Inference | Coursera | Columbia University | 6 周 | 链接 |
| Causal Diagrams | edX | Harvard University | 7 周 | 链接 |
| Causal Inference with R | Coursera | Duke University | 4 周 | 链接 |
| 因果推断入门 | B 站 | 王式安 | 10 小时 | 链接 |
付费课程¶
| 课程 | 平台 | 价格 | 特点 |
|---|---|---|---|
| Causal Inference A/B Testing | Udemy | $89 | A/B 测试实战 |
| Causal Machine Learning | DataCamp | $25/月 | ML 与因果结合 |
| 因果推断实战 | 极客时间 | ¥199 | 中文案例 |
🔧 工具库¶
Python¶
| 库 | 功能 | Stars | 链接 |
|---|---|---|---|
| Dowhy | 微软因果推断库,支持多种方法 | 5k+ | GitHub |
| EconML | 微软异质处理效应估计 | 4k+ | GitHub |
| CausalML | Uber 因果 ML 平台 | 3k+ | GitHub |
| CausalNex | 因果图与结构学习 | 1k+ | GitHub |
| pgmpy | 概率图模型(含因果图) | 6k+ | GitHub |
R¶
| 库 | 功能 | 链接 |
|---|---|---|
| dagitty | 因果图绘制与分析 | CRAN |
| causaleffect | 因果效应识别 | CRAN |
| MatchIt | 倾向得分匹配 | CRAN |
| twang | 加权调整 | CRAN |
📊 核心方法¶
1. 随机对照试验 (RCT)¶
黄金标准,但成本高、伦理限制多
# RCT 效果估计
def estimate_rct_effect(treatment, outcome):
"""
treatment: 0/1 数组
outcome: 连续结果
"""
import numpy as np
treatment_outcomes = outcome[treatment == 1]
control_outcomes = outcome[treatment == 0]
ate = np.mean(treatment_outcomes) - np.mean(control_outcomes)
se = np.sqrt(np.var(treatment_outcomes)/len(treatment_outcomes) +
np.var(control_outcomes)/len(control_outcomes))
t_stat = ate / se
p_value = 2 * (1 - scipy.stats.norm.cdf(abs(t_stat)))
return {
'ATE': ate,
'SE': se,
't_statistic': t_stat,
'p_value': p_value,
'significant': p_value < 0.05
}
2. 倾向得分匹配 (PSM)¶
适用场景: 观察性研究,选择偏差问题
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import NearestNeighbors
import numpy as np
def propensity_score_matching(X, treatment, outcome):
"""
倾向得分匹配
X: 协变量矩阵
treatment: 处理变量 (0/1)
outcome: 结果变量
"""
# 步骤 1: 估计倾向得分
ps_model = LogisticRegression()
ps_model.fit(X, treatment)
propensity_scores = ps_model.predict_proba(X)[:, 1]
# 步骤 2: 匹配
treated_idx = np.where(treatment == 1)[0]
control_idx = np.where(treatment == 0)[0]
# 最近邻匹配
matcher = NearestNeighbors(n_neighbors=1, metric='euclidean')
matcher.fit(propensity_scores[control_idx].reshape(-1, 1))
matches = matcher.kneighbors(
propensity_scores[treated_idx].reshape(-1, 1),
return_distance=False
)
matched_control_idx = control_idx[matches.flatten()]
# 步骤 3: 计算处理效应
treated_outcomes = outcome[treated_idx]
matched_control_outcomes = outcome[matched_control_idx]
ate = np.mean(treated_outcomes - matched_control_outcomes)
# 平衡性检验
standardized_diffs = []
for i in range(X.shape[1]):
mean_treated = np.mean(X[treated_idx, i])
mean_control = np.mean(X[matched_control_idx, i])
pooled_std = np.sqrt((np.var(X[treated_idx, i]) + np.var(X[matched_control_idx, i])) / 2)
std_diff = abs(mean_treated - mean_control) / pooled_std
standardized_diffs.append(std_diff)
return {
'ATE': ate,
'mean_standardized_diff': np.mean(standardized_diffs),
'balance_achieved': np.mean(standardized_diffs) < 0.1
}
3. 双重差分 (DID)¶
适用场景: 政策评估,有处理组和对照组的时间序列数据
import statsmodels.api as sm
import pandas as pd
def difference_in_differences(data, treatment_group, post_period):
"""
双重差分模型
data: DataFrame,包含 outcome, group, period 列
treatment_group: 处理组标识
post_period: 政策后时期标识
"""
# 构建 DID 变量
data['treated'] = (data['group'] == treatment_group).astype(int)
data['post'] = (data['period'] >= post_period).astype(int)
data['did'] = data['treated'] * data['post']
# 回归模型
X = sm.add_constant(data[['treated', 'post', 'did']])
y = data['outcome']
model = sm.OLS(y, X).fit()
did_effect = model.params['did']
did_se = model.bse['did']
did_pvalue = model.pvalues['did']
# 平行趋势检验
# (需要政策前多期数据,检验处理组和对照组趋势是否一致)
return {
'DID_effect': did_effect,
'SE': did_se,
'p_value': did_pvalue,
'significant': did_pvalue < 0.05,
'model_summary': model.summary()
}
4. 工具变量 (IV)¶
适用场景: 内生性问题(遗漏变量、反向因果)
from linearmodels.iv import IV2SLS
def instrumental_variable(Y, D, Z, X=None):
"""
工具变量估计
Y: 结果变量
D: 内生处理变量
Z: 工具变量
X: 外生协变量(可选)
"""
# 构建模型
if X is not None:
formula = 'Y ~ 1 + D + X'
instruments = 'Z + X'
else:
formula = 'Y ~ 1 + D'
instruments = 'Z'
# 两阶段最小二乘法
model = IV2SLS.from_formula(formula, data, instruments=instruments)
results = model.fit()
# 工具变量有效性检验
# 1. 相关性检验:第一阶段 F 统计量应 > 10
# 2. 排他性约束:工具变量只通过 D 影响 Y
return {
'LATE': results.params['D'],
'SE': results.bse['D'],
'p_value': results.pvalues['D'],
'first_stage_F': results.first_stage['F'],
'valid_instrument': results.first_stage['F'] > 10,
'summary': results.summary
}
5. 断点回归 (RDD)¶
适用场景: 处理分配基于连续变量的阈值
import numpy as np
from sklearn.linear_model import LinearRegression
def regression_discontinuity(Y, X, cutoff, bandwidth=None):
"""
断点回归
Y: 结果变量
X: 运行变量
cutoff: 断点阈值
bandwidth: 带宽(可选,默认最优带宽)
"""
if bandwidth is None:
# Silverman 规则选择带宽
bandwidth = 1.06 * np.std(X) * len(X)**(-1/5)
# 选择断点附近的样本
mask = np.abs(X - cutoff) < bandwidth
X_local = X[mask]
Y_local = Y[mask]
# 局部线性回归
def fit_local_regression(treatment_side):
if treatment_side == 'right':
local_mask = (X_local >= cutoff) & (X_local < cutoff + bandwidth)
else:
local_mask = (X_local < cutoff) & (X_local >= cutoff - bandwidth)
X_fit = X_local[local_mask].reshape(-1, 1)
y_fit = Y_local[local_mask]
model = LinearRegression()
model.fit(X_fit - cutoff, y_fit)
return model
left_model = fit_local_regression('left')
right_model = fit_local_regression('right')
# 估计断点处的跳跃
left_pred = left_model.predict([[0]])[0]
right_pred = right_model.predict([[0]])[0]
treatment_effect = right_pred - left_pred
return {
'treatment_effect': treatment_effect,
'bandwidth': bandwidth,
'n_left': len(left_model.predict(X_local[left_model.predict(X_local) < cutoff].reshape(-1, 1))),
'n_right': len(right_model.predict(X_local[right_model.predict(X_local) >= cutoff].reshape(-1, 1)))
}
6. 合成控制法 (Synthetic Control)¶
适用场景: 单一处理单元的政策评估
from sklearn.optimize import minimize
import numpy as np
def synthetic_control(Y_treated, Y_controls, X_treated, X_controls):
"""
合成控制法
Y_treated: 处理单元结果时间序列
Y_controls: 控制单元结果矩阵 (n_controls × time)
X_treated: 处理单元协变量
X_controls: 控制单元协变量矩阵
"""
n_controls = Y_controls.shape[0]
def objective(weights):
# 最小化预处理期拟合误差
synthetic_Y = np.dot(weights, Y_controls)
synthetic_X = np.dot(weights, X_controls)
mse_Y = np.mean((synthetic_Y - Y_treated)**2)
mse_X = np.mean((synthetic_X - X_treated)**2)
return mse_Y + mse_X
# 约束:权重和为 1,非负
constraints = [
{'type': 'eq', 'fun': lambda w: np.sum(w) - 1}
]
bounds = [(0, 1) for _ in range(n_controls)]
# 优化
result = minimize(objective, x0=np.ones(n_controls)/n_controls,
method='SLSQP', bounds=bounds, constraints=constraints)
optimal_weights = result.x
synthetic_outcome = np.dot(optimal_weights, Y_controls)
# 处理效应 = 实际值 - 合成值
treatment_effect = Y_treated - synthetic_outcome
return {
'weights': optimal_weights,
'synthetic_outcome': synthetic_outcome,
'treatment_effect': treatment_effect,
'optimization_success': result.success
}
📝 应用案例¶
案例 1: 评估营销活动效果¶
问题: 优惠券是否提升了用户消费?
方法: 倾向得分匹配 + 双重差分
# 数据准备
# - 处理组:收到优惠券的用户
# - 对照组:未收到优惠券的相似用户
# - 结果:消费金额
# - 协变量:历史消费、活跃度、人口统计
# 分析步骤
# 1. PSM 匹配相似用户
# 2. DID 比较处理组和对照组前后变化
# 3. 异质性分析:不同用户群体效果差异
# 业务决策
# - 如果 CATE > 0 且显著 → 扩大优惠券发放
# - 如果仅特定群体有效 → 精准营销
# - 如果无效 → 停止活动,避免浪费
案例 2: 评估新产品功能¶
问题: 新功能是否提升了用户留存?
方法: A/B 测试 + 因果森林
from econml.orf import DROrthoForest
# A/B 测试
# - 随机分配用户到实验组/对照组
# - 比较留存率差异
# 异质性分析(因果森林)
# 识别哪些用户从新功能中获益最多
# - 特征:使用频率、设备类型、地理位置等
# - 输出:每个用户的个性化处理效应
# 决策
# - 全量上线:ATE 显著为正
# - 精准推送:仅对 CATE>0 的用户开放
# - 迭代优化:针对无效群体改进功能
案例 3: 政策评估(最低工资)¶
问题: 提高最低工资是否影响就业?
方法: 断点回归 + 合成控制
# 断点回归设计
# - 运行变量:城市人口规模
# - 断点:达到某阈值自动提高最低工资
# - 比较断点两侧城市的就业变化
# 合成控制
# - 处理单元:实施新政的州
# - 控制池:未实施新政的州
# - 构造"反事实":如果没有新政会怎样
# 结论
# - 短期影响:就业变化不显著
# - 长期影响:低技能岗位减少 3-5%
# - 收入效应:低收入群体收入提升 8%
🔬 前沿研究¶
因果机器学习¶
| 方法 | 描述 | 代表论文 |
|---|---|---|
| 因果森林 | 估计异质处理效应 | Athey & Imbens (2016) |
| 双重机器学习 | 高维控制变量下的因果估计 | Chernozhukov et al. (2018) |
| 元学习器 | S-Learner, T-Learner, X-Learner | Künzel et al. (2019) |
| 因果表示学习 | 从观测数据学习因果结构 | Bengio et al. (2019) |
推荐资源¶
# 因果机器学习必读论文
must_read_papers = [
{
'title': 'Recurrent Causal Forests',
'authors': 'Athey, Imbens',
'year': 2016,
'contribution': '因果森林算法',
'link': 'https://arxiv.org/abs/1504.01132'
},
{
'title': 'Double/Debiased Machine Learning',
'authors': 'Chernozhukov et al.',
'year': 2018,
'contribution': '双重机器学习框架',
'link': 'https://arxiv.org/abs/1608.00060'
},
{
'title': 'Meta-learners for Heterogeneous Treatment Effects',
'authors': 'Künzel et al.',
'year': 2019,
'contribution': 'S/T/X-learner 对比',
'link': 'https://arxiv.org/abs/1706.03461'
}
]
📋 方法选择指南¶
决策树¶
graph TB
A[因果推断问题] --> B{能否 RCT?}
B -->|能| C[随机对照试验<br>黄金标准]
B -->|不能| D{是否有清晰断点?}
D -->|是| E[断点回归 RDD<br>内部效度高]
D -->|否| F{是否有面板数据?}
F -->|是| G{是否有政策冲击?}
G -->|是| H[双重差分 DID<br>常用政策评估]
G -->|否| I{是否有工具变量?}
F -->|否| I
I -->|是| J[工具变量 IV<br>解决内生性]
I -->|否| K{是否有可比控制组?}
K -->|是| L[倾向得分匹配 PSM<br>选择偏差修正]
K -->|否| M[合成控制法<br>单一处理单元]
style C fill:#4caf50,color:white
style E fill:#8bc34a
style H fill:#8bc34a
style J fill:#ffeb3b
style L fill:#ffeb3b
style M fill:#ffeb3b
方法对比¶
| 方法 | 识别假设 | 数据需求 | 内部效度 | 外部效度 |
|---|---|---|---|---|
| RCT | 随机分配 | 实验数据 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| PSM | 选择可观察 | 横截面 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| DID | 平行趋势 | 面板数据 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| IV | 工具变量有效性 | 横截面/面板 | ⭐⭐⭐⭐ | ⭐⭐ |
| RDD | 连续性假设 | 横截面 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| SCM | 无干预趋势稳定 | 面板数据 | ⭐⭐⭐⭐ | ⭐ |
🎯 学习路径¶
入门阶段 (1-2 个月)¶
第 1-2 周: 因果关系 vs 相关关系
- 阅读:《The Book of Why》
- 视频:3Blue1Brown 因果科学介绍
第 3-4 周: 反事实框架基础
- 阅读:《Causal Inference: What If》Ch1-4
- 实践:用 Python 实现 ATE 计算
第 5-8 周: 因果图基础
- 阅读:《Causal Inference in Statistics: A Primer》
- 实践:用 dagitty 绘制因果图
进阶阶段 (3-6 个月)¶
第 1-2 月: 计量经济学方法
- PSM、DID、IV、RDD
- 阅读:《Mostly Harmless Econometrics》
- 实践:Stata/Python 实现
第 3-4 月: 因果机器学习
- 因果森林、双重机器学习
- 阅读:EconML 文档
- 实践:EconML/CausalML 库
第 5-6 月: 实战项目
- A/B 测试设计与分析
- 政策评估项目
- 营销效果评估
📚 中文资源¶
博客与教程¶
| 资源 | 作者 | 链接 |
|---|---|---|
| 因果推断实战 | 数据科学家联盟 | 链接 |
| 计量经济学笔记 | 连玉君 | 链接 |
| 因果推断入门 | 知乎专栏 | 链接 |
视频课程¶
| 课程 | 讲师 | 平台 | 链接 |
|---|---|---|---|
| 因果推断导论 | 邱东 | 中国大学 MOOC | 链接 |
| 计量经济学 | 陈强 | 哔哩哔哩 | 链接 |
最后更新: 2026-06-01
相关文档: - decision-science-resources.md - 决策科学资源 - ab-testing-resources.md - A/B 测试资源 - machine-learning-resources.md - 机器学习资源
**因果推断资源专题 | 从相关到因果**
[返回顶部](#因果推断资源专题)