因果推断机器学习¶
一句话说明¶
因果推断回答"X 是否真的导致 Y?"而不只是"X 和 Y 相关"——在生信中用于识别真正的致病基因(而非伴随表达的基因),评估干预效果(如某种治疗是否有效)。
核心知识点¶
相关 vs 因果¶
混杂因子:C 同时影响 A 和 B,让 A、B 看起来相关,但没有直接因果。
核心框架¶
Pearl 因果层次: 1. 关联(观察):P(Y|X) —— 看到 X 时,Y 是多少 2. 干预(do-演算):P(Y|do(X=x)) —— 强制设定 X,Y 会怎样 3. 反事实:如果当时做了不同的选择,Y 会怎样
常用方法:
| 方法 | 适用场景 | 生信应用 |
|---|---|---|
| 随机对照试验 RCT | 最强因果证据 | 药物临床试验 |
| 工具变量 IV | 有自然实验 | 孟德尔随机化 |
| 双重差分 DiD | 前后对照研究 | 政策评估 |
| 倾向性得分匹配 PSM | 观察性研究 | 队列研究 |
| 因果森林 | 异质处理效应 | 精准医学 |
| DoWhy/EconML | Python 框架 | 通用因果分析 |
孟德尔随机化(MR)¶
利用遗传变异(SNP)作为工具变量,推断暴露因素对结局的因果效应: - 工具变量:SNP → 暴露 → 结局 - 假设:SNP 只通过暴露影响结局(不直接影响结局) - 应用:BMI 是否因果地导致 2 型糖尿病
实战代码¶
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
# ===== 1. 倾向性得分匹配(PSM)=====
# 场景:比较两组患者(治疗组 vs 对照组),消除混杂因子
np.random.seed(42)
n = 500 # 样本量
# 模拟观察数据:年龄、BMI、吸烟状态 → 影响是否接受治疗
age = np.random.normal(50, 10, n) # 年龄
bmi = np.random.normal(25, 5, n) # BMI
smoking = np.random.binomial(1, 0.3, n) # 吸烟(0/1)
# 治疗概率受年龄和 BMI 影响(混杂!)
treatment_prob = 1 / (1 + np.exp(-(0.05*age + 0.1*bmi - 6 + 0.5*smoking)))
treatment = np.random.binomial(1, treatment_prob, n) # 治疗分配(1=治疗,0=对照)
# 真实结局(治疗效果 = 0.3,另有年龄影响)
outcome = 0.3 * treatment + 0.02 * age + np.random.normal(0, 0.5, n)
df = pd.DataFrame({
'age': age, 'bmi': bmi, 'smoking': smoking,
'treatment': treatment, 'outcome': outcome
})
# 第1步:用逻辑回归估计倾向性得分
X_confounders = df[['age', 'bmi', 'smoking']]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_confounders)
ps_model = LogisticRegression()
ps_model.fit(X_scaled, df['treatment'])
# 倾向性得分 = 每个样本接受治疗的预测概率
df['propensity_score'] = ps_model.predict_proba(X_scaled)[:, 1]
# 第2步:最近邻匹配(每个治疗样本找最相近倾向得分的对照样本)
treated = df[df['treatment'] == 1].copy()
control = df[df['treatment'] == 0].copy()
matched_pairs = []
used_control_idx = set()
for i, t_row in treated.iterrows():
# 找倾向得分最接近的未被匹配的对照样本
available_control = control[~control.index.isin(used_control_idx)]
if len(available_control) == 0:
break
ps_diff = abs(available_control['propensity_score'] - t_row['propensity_score'])
best_match_idx = ps_diff.idxmin() # 最小差异的对照样本
matched_pairs.append({
'treated_outcome': t_row['outcome'],
'control_outcome': available_control.loc[best_match_idx, 'outcome']
})
used_control_idx.add(best_match_idx)
matched_df = pd.DataFrame(matched_pairs)
# 第3步:计算匹配后的平均治疗效应(ATT)
att = (matched_df['treated_outcome'] - matched_df['control_outcome']).mean()
print(f'倾向得分匹配估计的平均治疗效应 ATT: {att:.3f}')
print(f'真实治疗效应: 0.300')
# ===== 2. 因果森林(异质处理效应)=====
# pip install econml
try:
from econml.grf import CausalForest
cf = CausalForest(
n_estimators=100, # 树的数量
min_samples_leaf=10, # 叶子节点最少样本
random_state=42
)
X = df[['age', 'bmi', 'smoking']].values
T = df['treatment'].values
Y = df['outcome'].values
cf.fit(X, T, Y) # 拟合因果森林
# 为每个个体估计处理效应(个性化治疗效应)
te_pred = cf.effect(X)
print(f'\n个体处理效应估计(前5个): {te_pred[:5].round(3)}')
print(f'平均处理效应: {te_pred.mean():.3f}')
except ImportError:
print("需要安装 econml: pip install econml")
# ===== 3. 孟德尔随机化(简化演示)=====
# 工具变量分析:SNP → 暴露(BMI)→ 结局(糖尿病风险)
def mendelian_randomization_wald(beta_exposure, beta_outcome, se_exposure, se_outcome):
"""
Wald 估计量:最简单的 MR 方法
单一 SNP 工具变量
"""
# 因果效应估计 = SNP对结局的效应 / SNP对暴露的效应
causal_estimate = beta_outcome / beta_exposure
# Delta 法估计标准误
se_ratio = abs(causal_estimate) * np.sqrt(
(se_outcome/beta_outcome)**2 + (se_exposure/beta_exposure)**2
)
return causal_estimate, se_ratio
# 假设数据:某 SNP 与 BMI 的 GWAS 效应估计
beta_bmi_snp = 0.3 # SNP 对 BMI 的效应
se_bmi_snp = 0.05
beta_diabetes_snp = 0.12 # SNP 对糖尿病风险的效应
se_diabetes_snp = 0.03
causal_effect, se = mendelian_randomization_wald(
beta_bmi_snp, beta_diabetes_snp, se_bmi_snp, se_diabetes_snp
)
print(f'\nMR Wald 估计:BMI → 糖尿病因果效应 = {causal_effect:.3f} ± {se:.3f}')
print(f'95% CI: [{causal_effect - 1.96*se:.3f}, {causal_effect + 1.96*se:.3f}]')
面试常问点¶
Q: 相关和因果的区别?举个生信例子。 A: 冰淇淋销量和溺水死亡相关(因为夏天),但冰淇淋不导致溺水(共同原因是夏天)。生信例子:某基因在肿瘤中高表达,但它可能是旁观者而非驱动因子,需要功能实验或 MR 证明因果。
Q: 孟德尔随机化的三大假设? A: ①相关性:SNP 与暴露强相关;②独立性:SNP 不受混杂因子影响;③排他性:SNP 只通过暴露影响结局(不存在水平多效性)。
Q: 工具变量的核心思路? A: 找一个"自然实验"——只影响暴露变量、不直接影响结局的外生变量,用它切断混杂路径。
Q: 因果森林和普通随机森林的区别? A: 普通随机森林预测 E[Y|X],因果森林估计异质处理效应 E[Y(1)-Y(0)|X],即不同亚组的因果效应。
速查表¶
| 术语 | 解释 |
|---|---|
| 混杂因子 | 同时影响原因和结果的第三变量 |
| do-演算 | Pearl 的干预符号,P(Y|do(X)) |
| ATE | 平均处理效应(全体人群) |
| ATT | 处理组的平均处理效应 |
| PSM | 倾向性得分匹配 |
| 孟德尔随机化 | 以遗传变异为工具变量的流行病学方法 |
| 工具变量 IV | 只影响暴露的外生变量 |
| 水平多效性 | SNP 同时影响多个性状(MR 假设违背) |