返回首页

数据科学中的碰撞偏差:效果模拟

本文剖析碰撞偏差——过滤碰撞变量时相关性的扭曲。提供 Python 对均匀和正态数据的模拟及可视化。分析中避免的建议。

碰撞偏差:数据过滤导致的虚假连接
Advertisement 728x90

碰撞器偏差:数据筛选如何制造虚假相关性

碰撞器是指一个变量 C,它受到两个其他变量 A 和 B 的因果影响:A → C ← B。对 C 进行条件处理——无论是通过筛选还是分层——都会在 A 和 B 之间产生虚假的相关性。

现实世界中的例子:

  • 年龄 → 使用频率 → 质量(幸存下来的物品看起来质量更高)。
  • 智商 → 大学录取 → 家庭财富(在学生群体中,富裕家庭的孩子似乎智力较低)。
  • 天赋 → 成功 → 工作态度(成功的高天赋者显得更懒散)。

在数据科学中,这会导致误导性的模型:基于筛选后数据的梯度提升算法会继承这种偏差。

Google AdInline article slot

使用均匀分布数据进行模拟

我们生成 1,000 个独立点,分别从均匀分布 (0,100) 中抽取 A 和 B。当 A > 50 或 B > 50 时,设置碰撞器标志位为真。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from statsmodels.nonparametric.smoothers_lowess import lowess

NUMBER_OF_VALUES = 1000
A_RANGE = (0, 100)
B_RANGE = (0, 100)
A_THRESHOLD = 50
B_THRESHOLD = 50

a = np.random.uniform(*A_RANGE, NUMBER_OF_VALUES)
b = np.random.uniform(*B_RANGE, NUMBER_OF_VALUES)
data = pd.DataFrame({'a': a, 'b': b})
data['flag'] = (data['a'] > A_THRESHOLD) | (data['b'] > B_THRESHOLD)
print(f"相关系数 A 与 B:{data['a'].corr(data['b']):.2f}")
print(f"筛选后子集的相关系数:{data[data['flag']]['a'].corr(data[data['flag']]['b']):.2f}")

结果:

  • 完整数据集:相关系数 ≈ 0.00
  • 筛选子集:相关系数 ≈ -0.34

散点图可视化显示,移除未存活点(蓝色)后,趋势明显向下偏移。

Google AdInline article slot
sns.scatterplot(data=data, x='a', y='b', hue='flag', palette={True: 'red', False: 'blue'}, alpha=0.5)
sns.regplot(data=data, x='a', y='b', scatter=False, color='black')
plt.show()

筛选后,lmplot 显示负斜率:右上象限变得空缺,破坏了原本的平衡结构。

现实场景:正态分布模拟

现在我们使用 np.random.normal:A ~ N(50,5),B ~ N(30,5)。碰撞器是概率性的:先归一化数值,计算选择概率为 max(a_norm, b_norm)*1.5,截断到 [0,1],再根据随机抽样决定是否标记为真。

a = np.random.normal(loc=50, scale=5, size=NUMBER_OF_VALUES)
b = np.random.normal(loc=30, scale=5, size=NUMBER_OF_VALUES)
normal_data = pd.DataFrame({'a': a, 'b': b})
a_norm = (normal_data['a'] - normal_data['a'].min()) / (normal_data['a'].max() - normal_data['a'].min() + 1e-6)
b_norm = (normal_data['b'] - normal_data['b'].min()) / (normal_data['b'].max() - normal_data['b'].min() + 1e-6)
selection_prob = np.maximum(a_norm, b_norm) * 1.5
selection_prob = np.clip(selection_prob, 0, 1)
normal_data['flag'] = np.random.random(len(normal_data)) < selection_prob
print(f"完整数据集相关系数:{normal_data['a'].corr(normal_data['b']):.2f}")
print(f"筛选后子集相关系数:{normal_data[normal_data['flag']]['a'].corr(normal_data[normal_data['flag']]['b']):.2f}")

结果:

Google AdInline article slot
  • 完整数据集:相关系数 ≈ 0.03
  • 筛选子集:相关系数 ≈ -0.09

虽然效应较弱,但在 A/B 测试、实地研究或机器学习流程中仍具有显著影响。

如何避免分析中的碰撞器偏差

  • 绘制 DAG 图:使用有向无环图在分析前识别潜在碰撞器。
  • 避免基于结果的筛选:分析全人群,或采用 IPCW(逆概率删失加权)方法。
  • 筛选前后检查相关性:对比不同组别间的趋势变化。
  • 使用工具变量:在怀疑存在偏差时进行因果推断。
  • 借助贝叶斯网络:显式建模依赖关系与条件关联。

核心要点

  • 碰撞器偏差发生在对共同原因进行条件处理时,导致人为的负相关。
  • 均匀分布模拟得相关系数 ≈ -0.34;正态分布模拟得 ≈ -0.09——效应强度随数据结构而变化。
  • 与幸存者偏差、伯克森悖论及选择偏差密切相关。
  • 数据筛选前务必绘制 DAG 图。
  • 在机器学习中:筛选后的数据会导致模型偏差,造成特征重要性被低估或高估。

— Editorial Team

Advertisement 728x90

继续阅读