/ / /
第22讲:p值挖掘与多重比较偏差 (p-Hacking and Multiple Comparisons Bias)
🔴
入学要求
💯
能力测试
🛣️
课程安排
🕹️
研究资源

第22讲:p值挖掘与多重比较偏差 (p-Hacking and Multiple Comparisons Bias)

💡

查看全集:💎Quantopia量化分析56讲

当我们在同一数据集上进行多次统计检验时,偶然得到显著性结果的概率会大大增加,这就是多重比较偏差的概念。这种现象就像买彩票——买的次数越多,中奖几率越大,但大部分中奖结果只是运气。

生活案例:同时服用多种感冒药,恰巧症状好转时,可能错误归因于某药物有效,而实际是病程自然结束。

一、核心概念解析

1.1 p值的正确理解

# 正确使用p值的示例
cutoff = 0.05
p_value = 0.03  # 假设的检验结果

if p_value < cutoff:
    print("拒绝原假设")
else:
    print("未能拒绝原假设")

二、实验演示:随机数据中的虚假关联

2.1 创建随机数据集

import numpy as np
import pandas as pd
import scipy.stats as stats

N = 20  # 20个独立时间序列
T = 100 # 每个序列100个观测点

df = pd.DataFrame({f'X{i}': np.random.normal(0, 1, T) for i in range(N)})

2.2 执行多重相关性检验

significant_pairs = []
cutoff = 0.05

for i in range(N):
    for j in range(i+1, N):
        _, p = stats.spearmanr(df[f'X{i}'], df[f'X{j}'])
        if p < cutoff:
            significant_pairs.append((i, j))

print(f"发现显著相关对数量:{len(significant_pairs)}")

2.3 理论假阳性计算

多重比较中预期假阳性(Expected False Positives)的计算公式:

N(N1)2×α\frac{N(N-1)}{2} \times \alpha

其中:

expected_fp = (20*19/2) * 0.05  # 输出9.5

三、解决方案:Bonferroni校正

3.1 校正原理

将显著性水平调整为:

αnew=αNumber of Tests\alpha_{new} = \frac{\alpha}{Number\ of\ Tests}

这是Bonferroni校正的计算公式,其中:

total_tests = 20*19//2
new_cutoff = 0.05 / total_tests  # 0.000263

3.2 校正后实验

corrected_pairs = []
for i in range(N):
    for j in range(i+1, N):
        _, p = stats.spearmanr(df[f'X{i}'], df[f'X{j}'])
        if p < new_cutoff:
            corrected_pairs.append((i, j))

print(f"校正后显著对数量:{len(corrected_pairs)}")

3.3 方法对比

方法优点缺点
不做校正灵敏度高假阳性率高
Bonferroni控制总体错误率过于保守
分阶段验证平衡灵敏度特异性需要额外数据

四、实战案例:股票数据中的虚假相关性

4.1 获取真实金融数据

import yfinance as yf

# 获取10只科技股数据
symbols = ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'META',
           'TSLA', 'NVDA', 'INTC', 'ADBE', 'CSCO']
data = yf.download(symbols, start='2020-01-01', end='2023-01-01')['Close']

4.2 相关性分析

significant_pairs = []
cutoff = 0.05

for i in range(len(symbols)):
    for j in range(i+1, len(symbols)):
        stock1 = data[symbols[i]].pct_change().dropna()
        stock2 = data[symbols[j]].pct_change().dropna()
        _, p = stats.spearmanr(stock1, stock2)
        if p < cutoff:
            significant_pairs.append((symbols[i], symbols[j]))

print(f"发现显著相关股票对:{significant_pairs}")

五、防御策略与最佳实践

5.1 事前预防措施

5.2 事后修正方法

5.3 思考练习

  1. 当N=50时,使用α=0.05会预期多少个假阳性?
  1. 如果将Bonferroni校正应用于N=100的股票池,新α值是多少?
  1. 设计一个两阶段验证方案来平衡灵敏度和特异度

六、关键要点总结

通过系统理解这些原理并应用防御策略,研究者可以显著提升分析的可靠性。记住:真正的发现应该经得起时间和新数据的考验。

附:练习合集