因果推断导论:从统计相关性到因果关系的技术实现路径

1次阅读
没有评论

共计 2828 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

为什么相关性不等于因果性?

在广告点击率分析中,我们经常观察到「高收入用户点击奢侈品广告更多」的现象。传统统计方法可能得出『收入水平影响广告点击』的结论,但实际上存在多种可能性:

因果推断导论:从统计相关性到因果关系的技术实现路径

  • 真实因果:高收入导致奢侈品点击($income \to click$)
  • 反向因果:频繁点击奢侈品广告的用户被系统标记为高收入($click \to income$)
  • 混杂因素:大城市用户既收入高又对奢侈品感兴趣($city \to income$,$city \to click$)

因果推断 vs 传统统计

传统统计方法(如回归分析)只能识别变量间的 关联性,而因果推断需要回答反事实问题:

如果对同一用户同时展示 / 不展示广告(实际不可能),点击行为会如何变化?

do-calculus 数学基础

Judea Pearl 提出的 do- 算子形式化定义了干预(intervention):

$$
P(Y|do(X=x)) \neq P(Y|X=x)
$$

关键差异在于:

  1. $P(Y|X=x)$ 反映观察到的关联
  2. $P(Y|do(X=x))$ 表示强制设定 $X=x$ 后的结果分布

核心实现:倾向得分匹配(PSM)

Python 实现代码

import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

# 生成模拟数据(广告曝光 T, 用户特征 X, 点击 Y)data = pd.DataFrame({'age': np.random.normal(35, 5, 1000),
    'income': np.random.lognormal(10, 0.3, 1000),
    'T': np.random.binomial(1, p=0.4, size=1000),  # 是否曝光广告
    'Y': np.zeros(1000)
})

# 标准化特征
scaler = StandardScaler()
X = scaler.fit_transform(data[['age', 'income']])

# 计算倾向得分(propensity score)ps_model = LogisticRegression()
ps_model.fit(X, data['T'])
data['ps'] = ps_model.predict_proba(X)[:, 1]

# 最近邻匹配(1:1)from sklearn.neighbors import NearestNeighbors
treated = data[data['T']==1]
control = data[data['T']==0]

nbrs = NearestNeighbors(n_neighbors=1).fit(control[['ps']])
_, indices = nbrs.kneighbors(treated[['ps']])
matched_control = control.iloc[indices.flatten()]

# 平衡性检查(标准化均值差 SMD < 0.1)def smd(a, b):
    return (a.mean() - b.mean()) / np.sqrt((a.var() + b.var())/2)

print(f"Age SMD: {smd(treated['age'], matched_control['age']):.3f}")
print(f"Income SMD: {smd(treated['income'], matched_control['income']):.3f}")

因果图构建与验证

使用 DAG(有向无环图)明确变量间的因果关系假设:

import networkx as nx
import matplotlib.pyplot as plt

dag = nx.DiGraph()
dag.add_edges_from([('city', 'income'),
    ('city', 'click'),
    ('income', 'click'),
    ('ad_exposure', 'click')
])

# 可视化
pos = nx.spring_layout(dag)
nx.draw(dag, pos, with_labels=True, node_size=2000, font_weight='bold')
plt.show()

# 识别混杂因子(需要控制的变量集)print("Backdoor paths:",
    nx.d_separated(dag, {'ad_exposure'}, {'click'}, {'income'}))

性能优化技巧

高维特征处理

当特征维度 $p$ 很大时,双重稳健估计(Doubly Robust)结合了倾向得分和结果模型优势:

$$
\hat{\tau}_{DR} = \frac{1}{n}\sum \left[
\frac{T_i(Y_i – \hat{\mu}_1(X_i))}{\hat{e}(X_i)} + \hat{\mu}_1(X_i) \right] – \left[
\frac{(1-T_i)(Y_i – \hat{\mu}_0(X_i))}{1-\hat{e}(X_i)} + \hat{\mu}_0(X_i) \right]
$$

隐变量敏感性分析

使用 R 包 sensemakr 或以下公式评估未观测变量 $U$ 的影响:

$$
\Gamma = \frac{P(U=1|T=1)/P(U=1|T=0)}{P(U=0|T=1)/P(U=0|T=0)}
$$

生产环境挑战

样本重叠问题

当同一个用户出现在实验组和对照组时,采用交叉验证或聚类标准误:

from statsmodels.stats.weightstats import DescrStatsW

# 聚类在用户 ID
res = DescrStatsW(outcome, weights=ipw, cluster=data['user_id'])
print(res.ttest_mean())

缺失数据处理

对于非随机缺失(MNAR),使用多重插补或模式混合模型:

from statsmodels.imputation.mice import MICEData

imp = MICEData(data[['age', 'income', 'T', 'Y']])
imp.update_all()  # 迭代 5 次
completed_data = imp.data

扩展学习路线

  1. 基础理论
  2. 《Causal Inference: The Mixtape》- Scott Cunningham
  3. Pearl 的因果图模型(DAG)

  4. 算法实现

  5. PC 算法(Peter-Clark)用于因果发现
  6. 微软的 DoWhy 库

  7. 前沿方向

  8. 时变因果(Dynamic Treatment Regimes)
  9. 异质性因果效应(CATE)

实践心得

在电商场景应用因果推断时,我们发现:

  • 单纯 PSM 在特征高度重叠时效果较好,但对极端倾向得分敏感
  • 双重差分(DID)更适合面板数据,但需要平行趋势假设
  • 工具变量(IV)的寻找往往依赖业务知识而非纯数据驱动

建议从 AB 测试的扩展场景开始实践,逐步过渡到观测数据分析。

正文完
 0
评论(没有评论)