机器学习与因果推断 - 第三讲:有向无环图
用图形化方法思考因果:完整讲义
1 引言:为什么需要DAG?
1.1 从混淆变量到图形化思考
在之前的课程中,我们学习了混淆变量(Confounding Variables)如何导致选择偏误。当处理变量的分配不是随机时,接受处理和未接受处理的群体在其他方面也可能不同——这些差异会混淆我们对因果效应的估计。
传统的处理方法通常建议”控制所有可观测变量”,但这种策略存在严重问题:
- 控制中介变量会阻断真实的因果路径,导致低估效应
- 控制碰撞变量会打开虚假的统计关联,造成偏误
- 数据驱动地选择控制变量可能引入过拟合和虚假发现
有向无环图(Directed Acyclic Graphs, DAG)提供了一种系统化的方法来思考变量之间的因果关系,帮助我们:
- 可视化地表示因果假设
- 识别哪些变量需要控制
- 识别哪些变量绝对不能控制
- 指导研究设计和估计策略
1.2 DAG的核心价值
DAG让因果假设从”研究者心中的想法”变成了”可以讨论、批评和检验的图表”。这种可视化带来的好处包括:
1. 明确因果假设
DAG要求研究者明确:哪些变量是原因的,哪些是结果的,哪些是共同原因。这种明确性使得假设可以被同行评审和讨论。
2. 系统化识别偏误来源
通过路径分析,DAG可以系统地识别所有可能的混淆路径,以及如何通过控制特定变量来阻断这些路径。
3. 避免控制变量陷阱
DAG明确警告我们:并非所有变量都应该控制。特别是碰撞节点(Collider),控制它们反而会引入偏误。
4. 指导研究设计
在收集数据之前绘制DAG,可以帮助研究者思考:需要测量哪些变量?是否存在未观测的混淆因素?是否需要改变抽样策略?
2 DAG基础符号
2.1 基本要素
一个有向无环图(DAG)包含三个基本要素:
节点(Nodes)
节点表示随机变量。在因果推断中,我们通常关注: - :处理变量(Treatment/Exposure) - :结果变量(Outcome) - :其他变量(可能是混淆因素、中介变量、碰撞节点等)
有向边(Directed Edges)
有向边用箭头表示(),表示对有直接的因果效应。箭头的方向表示因果关系的方向——从原因指向结果。
无环性(Acyclicity)
“无环”意味着图中不能存在循环路径。即,如果导致,导致,那么不能导致。这反映了因果关系的时序性:原因必须在结果之前发生。
2.2 三种基本路径结构
DAG中的所有路径都可以分解为三种基本结构的组合:
2.2.1 链式结构(Chain)
结构:
在链式结构中,是中介变量(Mediator)——它是影响的中间环节。
例子:教育 → 职业技能 → 收入
- 上大学提高职业技能
- 更高的职业技能带来更高收入
- 教育对收入的总效应部分通过职业技能的提升实现
控制策略: - 如果想估计总效应,不要控制 - 如果想估计直接效应(不通过的部分),可以控制
2.2.2 分叉结构(Fork)
结构:
在分叉结构中,是混淆变量(Confounder)——它是和的共同原因。
例子:能力 → 教育;能力 → 收入
- 能力强的人更可能接受高等教育
- 能力强的人即使没有高等教育也可能收入更高
- 简单比较大学生和非大学生的收入会夸大教育回报
控制策略: - 必须控制才能识别对的因果效应 - 如果不控制,后门路径保持开放,造成偏误
2.2.3 碰撞结构(Collider)
结构:
在碰撞结构中,是碰撞节点(Collider)——它同时受到和的影响。
关键洞察:在未控制时,和是独立的(假设它们原本无因果关系)。但是,一旦控制,和会变得虚假相关!
例子:美貌 → 成为明星 ← 才华
- 成为电影明星可能需要美貌或才华(或两者兼备)
- 在一般人群中,美貌和才华可能是独立的
- 但在”明星”这个子群体中,美貌和才华会呈现负相关
- 这是因为:如果已经有美貌,才华的要求可以降低;如果已经有才华,美貌的要求可以降低
控制策略: - 绝对不要控制碰撞节点 - 控制会打开虚假路径,创造本不存在的相关
3 后门准则
3.1 后门路径的概念
后门路径(Backdoor Path)是指从处理变量到结果变量的非因果路径,满足以下条件:
- 路径以指向的箭头开始(即路径开始于)
- 路径包含任何方向的边(可以是或)
为什么后门路径会造成偏误?
后门路径创建了和之间的统计相关,但这种相关不是因果关系,而是混淆造成的。例如,路径中,的变化会同时影响和,使得和看起来相关,即使并不导致。
3.2 后门准则的正式定义
后门准则(Backdoor Criterion)
对于处理变量和结果变量,变量集合满足后门准则,如果:
- 阻断了所有从到的后门路径
- 不包含的任何后代(包括本身)
为什么条件2很重要?
条件2确保我们不会: - 控制碰撞节点(碰撞节点是和某个其他变量的共同后代) - 控制中介变量(中介变量是的后代)
3.3 后门准则的数学含义
如果变量集合满足后门准则,那么我们可以用观察数据识别因果效应:
其中: - 表示干预后的分布(即因果效应) - 是给定和的条件分布 - 是的边缘分布
实际含义:通过调整(控制),我们可以消除后门路径造成的偏误,获得因果效应的无偏估计。
3.4 应用示例:教育回报研究
考虑研究”大学教育对收入的因果效应”。相关的DAG可能包括:
变量: - :是否上大学 - :收入 - :能力(不可完全观测) - :家庭社会经济地位 - :高中成绩 - :职业选择 - :婚姻状况
因果路径: - 大学教育 → 收入(直接效应) - 大学教育 → 职业选择 → 收入(间接效应)
后门路径: 1. 教育 能力 收入 2. 教育 家庭背景 能力 收入 3. 教育 高中成绩 能力 收入
控制策略:
应该控制:能力(尽可能代理)、家庭背景、高中成绩 - 阻断所有后门路径 - 这些不是的后代
不应该控制: - 职业选择(中介变量,控制会低估总效应) - 婚姻状况(可能是碰撞节点:教育 → 婚姻 ← 收入潜力)
4 碰撞偏误的深入分析
4.1 名人效应:直观理解碰撞偏误
电影明星的例子是理解碰撞偏误的经典案例:
设定: - :美貌 - :演技 - :成为明星
因果关系: - 美貌有助于成为明星: - 演技有助于成为明星: - 是碰撞节点
悖论:
在普通人群中,美貌和演技可能不相关(或只有弱相关)。但在”明星”这个子群体中: - 我们看到很多美貌但演技一般的明星 - 我们看到很多演技好但美貌一般的明星 - 美貌和演技呈现负相关!
解释:这不是因为美貌和演技真的此消彼长,而是成为明星的选择机制造成的。如果一个人在美貌方面得分很高,那么在演技方面的”门槛”就会降低;反之亦然。
4.2 碰撞偏误在学术研究中的常见形式
4.2.1 样本选择偏误
问题:如果研究样本本身是基于碰撞节点选择,偏误就存在了。
例子:研究成功人士的特征 - 成功 = f(能力, 机遇) - 能力和机遇都影响成功(成为成功人士) - 在成功人士样本中,能力和机遇可能负相关 - 但这只是选择效应,不是真实的权衡
4.2.2 控制结果变量
问题:有时研究者会无意中控制处理或结果的代理变量。
例子:研究幸福感对收入的影响 - 幸福感可能影响婚姻决策 - 收入也可能影响婚姻决策 - 婚姻状态是碰撞节点 - 如果控制婚姻状态,会引入偏误
4.2.3 幸存者偏误
例子:研究企业培训的效果 - 培训可能影响员工绩效 - 高绩效员工更可能被保留(不被裁员) - 留存状态是碰撞节点:培训 → 留存 ← 绩效 - 如果只分析留存的员工,会低估培训效果(因为培训效果差的已经离开)
4.3 真实案例:性别工资差距
常见发现:控制职业后,性别工资差距减小或消失
DAG分析:
职业选择可能是碰撞节点: - 性别歧视可能影响职业选择 - 个人偏好和能力影响职业选择 - 职业收入反映歧视和偏好
控制职业的潜在问题:
如果歧视通过限制女性进入高收入职业来运作,那么”控制职业”就是在控制歧视的渠道。这会低估歧视的总效应。
正确的解释: - 总歧视效应 = 同职业内的工资差距 + 职业选择受限造成的损失 - 只控制前者会遗漏后者
5 两种因果推断框架的比较
5.1 潜在结果框架(Rubin因果模型)
核心概念:
对于每个个体,存在两种潜在结果: - :接受处理的结果 - :未接受处理的结果
因果效应: - 个体处理效应: - 平均处理效应:
识别假设: 1. 无混淆假设(Unconfoundedness):处理分配与潜在结果独立,条件于可观测变量 2. 正向性(Positivity/Overlap):对于所有协变量值, 3. SUTVA:个体的潜在结果不受他人处理状态影响
优势: - 数学表达精确 - 估计方法成熟(回归、匹配、加权、双重差分等) - 易于进行统计推断
5.2 DAG框架(Pearl因果图)
核心概念:
- 节点:随机变量
- 有向边:直接因果效应
- 路径:节点间的连接序列
- -分离(d-separation):判断条件独立性的图形准则
识别规则:
- 后门准则:阻断所有后门路径
- 前门准则:利用中介变量识别因果效应
- -演算:从观察分布推导干预分布的通用方法
优势: - 可视化因果关系 - 系统化识别偏误来源 - 指导变量选择 - 处理复杂因果结构(如多中介、反馈循环等)
5.3 两种框架的互补性
| 维度 | 潜在结果框架 | DAG框架 |
|---|---|---|
| 核心问题 | “效应有多大?” | “能否识别效应?” |
| 表达形式 | 数学方程和假设 | 图形结构 |
| 主要用途 | 估计和推断 | 研究设计和假设检验 |
| 识别条件 | 无混淆假设(CIA) | 后门准则、-分离 |
| 变量选择 | 基于理论判断 | 基于路径分析 |
| 中介分析 | 潜在结果中介模型 | 前门准则 |
| 处理复杂选择 | 较困难 | 系统化方法 |
最佳实践:
- 研究设计阶段:使用DAG理清因果结构,识别需要控制的变量
- 估计阶段:使用潜在结果框架的估计方法(回归、匹配、双重差分等)
- 敏感性分析:用DAG识别可能的未观测混淆因素,用潜在结果框架评估敏感性
5.4 从两种视角看同一问题
5.4.1 混淆偏误
潜在结果视角:
处理组和对照组在反事实上不可比——如果处理组未接受处理,他们的结果会与实际未接受处理的对照组不同。
DAG视角:
存在从到的开放后门路径。例如,,其中是混淆变量。
解决方案:
控制阻断后门路径。潜在结果框架证明这可以恢复可比较性;DAG框架系统化识别需要控制的变量。
5.4.2 碰撞偏误
潜在结果视角:
条件化(控制)一个变量导致样本选择,破坏了处理组和对照组的可比性。条件分布不再反映原始总体的特征。
DAG视角:
控制的变量是碰撞节点,打开了一条原本封闭的虚假路径。和通过碰撞节点产生了虚假相关。
解决方案:
不要控制碰撞节点。在潜在结果框架中,这意味着避免基于结果或其代理变量进行选择;在DAG框架中,这意味着识别并避免控制碰撞节点。
6 如何用DAG指导研究设计
6.1 DAG分析的五步法
6.1.1 步骤1:绘制DAG
原则: - 列出所有可能影响因果关系的变量 - 基于理论、先验知识和领域专家意见 - 包含可观测和不可观测变量 - 与同事、导师讨论,完善图表
注意事项: - DAG反映的是你的因果假设,不是数据的相关性 - 不同的研究者可能有不同的DAG——这是正常的科学讨论 - 随着研究深入,DAG可以被修正
6.1.2 步骤2:识别因果路径
从处理变量到结果变量,找出所有可能的因果路径: - 直接效应: - 间接效应:(是中介)
重要:确保你不会在后续步骤中阻断这些路径(除非你只想估计直接效应)。
6.1.3 步骤3:识别后门路径
找出所有从到的后门路径: 1. 路径以指向的箭头开始 2. 路径最终到达 3. 路径不是直接的因果路径
例子: - - -
6.1.4 步骤4:确定调整策略
找出满足后门准则的变量集合:
必须满足: 1. 阻断所有后门路径 2. 不包含的后代
可能的集合: - 通常有多个满足条件的变量集合 - 选择最容易测量、最不容易出错的集合 - 考虑统计功效(调整变量过多会降低估计精度)
6.1.5 步骤5:敏感性分析
未观测混淆因素:
DAG中可能包含不可观测的变量。思考: - 如果存在未观测的混淆因素,效应估计会如何变化? - 需要多强的未观测混淆才能解释掉观察到的效应?
工具: - VanderWeele和Ding的敏感性分析 - 界限分析(Bounding Analysis) - 阴性对照(Negative Controls)
6.2 实践案例:培训项目效果评估
本节通过完整的Python代码示例,展示如何使用DAG指导研究设计、生成模拟数据、进行回归分析,并比较不同控制策略的效果。
6.2.1 案例背景
某公司想评估新员工培训的效果。相关的变量包括:
- 处理变量 :是否参加培训
- 结果变量 :工作绩效
- 混淆变量 :能力(影响培训和绩效)
- 中介变量 :技能掌握(培训→技能→绩效)
- 碰撞变量 :留任状态(受绩效和培训共同影响)
6.2.2 模拟数据生成
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
import networkx as nx
import warnings
warnings.filterwarnings('ignore')
# 设置随机种子
np.random.seed(42)
n = 1000
true_effect = 2.0
# 生成变量
C = np.random.normal(5, 1.5, n) # 能力
D = (np.random.uniform(0, 1, n) < 1/(1+np.exp(-(C-5)/2))).astype(int) # 培训
M = 0.7*D + 0.3*C + np.random.normal(0, 0.5, n) # 技能
Y = true_effect*D + 1.5*C + 0.5*M + np.random.normal(0, 1, n) # 绩效
L = (np.random.uniform(0, 1, n) < 1/(1+np.exp(-(0.3*Y+0.5*D-3)))).astype(int) # 留任
data = pd.DataFrame({
'training': D,
'performance': Y,
'ability': C,
'skill': M,
'retention': L
})6.2.3 使用NetworkX/CausalGraph绘制DAG
# 创建有向图
G = nx.DiGraph()
nodes = [
('C', {'label': '能力(C)', 'type': 'confounder', 'color': '#FF6B6B'}),
('D', {'label': '培训(D)', 'type': 'treatment', 'color': '#4ECDC4'}),
('M', {'label': '技能(M)', 'type': 'mediator', 'color': '#95E1D3'}),
('Y', {'label': '绩效(Y)', 'type': 'outcome', 'color': '#F38181'}),
('L', {'label': '留任(L)', 'type': 'collider', 'color': '#FFA07A'})
]
G.add_nodes_from([(n, attr) for n, attr in nodes])
# 添加因果边
edges = [('C','D'), ('C','Y'), ('D','M'), ('M','Y'), ('D','Y'), ('D','L'), ('Y','L')]
for u, v in edges:
G.add_edge(u, v)
# 绘制图形
fig, ax = plt.subplots(figsize=(8, 6))
pos = {'C': (0, 2), 'D': (-1.5, 1), 'M': (0, 1.2), 'Y': (1.5, 1), 'L': (0, 0)}
node_colors = [G.nodes[n]['color'] for n in G.nodes()]
nx.draw_networkx_nodes(G, pos, node_color=node_colors, node_size=2000,
edgecolors='black', linewidths=2, ax=ax)
nx.draw_networkx_edges(G, pos, edge_color='#333333', width=2.5, arrows=True,
arrowstyle='-|>', arrowsize=28, ax=ax,
connectionstyle='arc3,rad=0.10')
labels = {n: G.nodes[n]['label'] for n in G.nodes()}
nx.draw_networkx_labels(G, pos, labels, font_size=10, font_weight='bold', ax=ax)
ax.set_title('培训效果评估的DAG结构', fontsize=14, fontweight='bold')
ax.axis('off')
plt.show()
print(f"DAG统计: {G.number_of_nodes()}节点, {G.number_of_edges()}边, 2条后门路径")6.2.4 不同控制策略的回归分析
# 5种控制策略比较
models = {
'模型1(不控制)': sm.OLS(data['performance'], sm.add_constant(data['training'])).fit(),
'模型2(控制C)✓': sm.OLS(data['performance'], sm.add_constant(data[['training','ability']])).fit(),
'模型3(控制M)✗': sm.OLS(data['performance'], sm.add_constant(data[['training','skill']])).fit(),
'模型4(控制C+M)': sm.OLS(data['performance'], sm.add_constant(data[['training','ability','skill']])).fit(),
'模型5(控制L)✗': sm.OLS(data['performance'], sm.add_constant(data[['training','retention']])).fit()
}
print(f"真实处理效应: {true_effect:.3f}")
print("=" * 65)
results = []
for name, model in models.items():
coef = model.params['training']
results.append({
'模型': name,
'估计值': f"{coef:.3f}",
'偏差': f"{coef-true_effect:+.3f}",
'R²': f"{model.rsquared:.3f}"
})
results_df = pd.DataFrame(results)
print(results_df.to_string(index=False))6.2.5 结果解读
| 模型 | 评估 | 问题说明 |
|---|---|---|
| 模型1:朴素回归(不控制) | ✗ 有偏 | 包含能力(C)的混淆效应,能力强的人更可能参加培训且绩效更高 |
| 模型2:控制混淆变量C | ✓ 正确 | 阻断后门路径 C→D 和 C→Y,最接近真实效应(2.0) |
| 模型3:控制中介变量M | ✗ 低估 | 阻断了间接效应路径 D→M→Y,严重低估总效应 |
| 模型4:控制C+M | △ 部分正确 | 估计直接效应(不包括间接效应),适用于特定研究目标 |
| 模型5:控制碰撞变量L | ✗✗ 严重错误 | 控制了碰撞节点,打开虚假路径,估计严重有偏 |
核心教训:
- 必须控制混淆变量(C):阻断后门路径,获得无偏估计
- 不要控制中介变量(M):除非研究目标仅为直接效应
- 绝对不能控制碰撞变量(L):会引入新的偏误,破坏估计的有效性
- DAG是选择控制变量的科学依据:基于图形分析而非直觉选择控制变量
6.3 使用DAG的实用建议
6.3.1 推荐工具
在线工具: - DAGitty(dagitty.net):绘制DAG、识别最小调整集、进行-分离分析 - Causal Fusion:更复杂的因果分析平台
R包: - ggdag:绘制美观的DAG - dagitty:与DAGitty在线工具交互
Python包: - CausalGraph:构建和分析因果图 - pgmpy:概率图模型库
6.3.2 常见错误与避免
- 绘制DAG时包含数据中的相关性
- DAG应该基于因果假设,不是数据的相关性
- 避免”我看到X和Y相关,所以在DAG中加一条边”
- 遗漏关键变量
- 特别是混淆因素
- 即使不可观测,也应该在DAG中标出
- 混淆链式结构和碰撞结构
- 仔细观察箭头的方向
- 碰撞节点有两个箭头指向它
- 过度控制
- 不要控制所有可观测变量
- 使用DAG指导选择
- 忽视样本选择
- 考虑数据收集过程本身是否引入偏误
- 样本是否基于碰撞节点选择?
7 总结
7.1 核心要点
本讲介绍了有向无环图(DAG)作为因果推断的图形化工具:
- DAG基础
- 节点表示变量,有向边表示因果效应
- 三种路径结构:链式(中介)、分叉(混淆)、碰撞(虚假相关)
- 后门准则
- 识别所有后门路径
- 找到满足后门准则的控制变量集合
- 阻断混淆路径,恢复因果关系的无偏估计
- 碰撞偏误
- 控制碰撞节点会打开虚假路径
- 样本选择可能引入偏误
- 避免控制处理或结果的代理变量
- 两种框架的结合
- DAG用于研究设计和变量选择
- 潜在结果框架用于估计和推断
- 两者互补,共同服务于因果推断
7.2 实践检查清单
在开始任何因果推断研究时,考虑以下问题:
7.3 进一步阅读
入门读物: - Pearl, J., & Mackenzie, D. (2018). The Book of Why. Basic Books. - Cunningham, S. (2021). Causal Inference: The Mixtape, Chapter 3.
进阶读物: - Pearl, J. (2009). Causality: Models, Reasoning, and Inference (2nd ed.). Cambridge University Press. - Morgan, S. L., & Winship, C. (2014). Counterfactuals and Causal Inference: Methods and Principles for Social Research (2nd ed.). Cambridge University Press. - Hernán, M. A., & Robins, J. M. (2020). Causal Inference: What If. Chapman & Hall/CRC.
在线资源: - DAGitty: https://dagitty.net/ - Causal Inference Playlist: https://www.youtube.com/playlist?list=PLoYXqjI7xzXa_8E5fQ2q3z5u5z5z5z5z5