Условие
В тесте 12 метрик. Какие p-value считать значимыми по Bonferroni, по Benjamini-Hochberg (FDR 5%)?
Решение
Подход
- Bonferroni: контролирует FWER (вероятность ≥1 ложного срабатывания) ≤ α. Порог:
α/m. - Benjamini-Hochberg (BH): контролирует FDR (ожидаемая доля ложных среди отвергнутых) ≤ q. Сортируем p_(1)≤...≤p_(m), отвергаем все p_(i) ≤ i·q/m, начиная сверху.
Bonferroni более консервативен, BH мощнее при многих истинных эффектах.
Реализация
import numpy as np
def bonferroni(pvals, alpha=0.05):
m = len(pvals)
return np.array(pvals) < alpha/m
def benjamini_hochberg(pvals, q=0.05):
p = np.array(pvals)
m = len(p)
order = np.argsort(p)
p_sorted = p[order]
thresh = q * np.arange(1, m+1) / m
# Найти самый большой i с p_(i) <= q*i/m
below = p_sorted <= thresh
if not below.any():
return np.zeros(m, dtype=bool)
k = np.max(np.where(below)[0])
rejected_sorted = np.zeros(m, dtype=bool)
rejected_sorted[:k+1] = True
# Развернуть
rejected = np.zeros(m, dtype=bool)
rejected[order] = rejected_sorted
return rejected
# Пример: 12 p-value
pvals = [0.001, 0.008, 0.012, 0.020, 0.033, 0.041,
0.049, 0.062, 0.10, 0.13, 0.25, 0.51]
print("Bonferroni:", bonferroni(pvals).sum(), "отвергнуто (порог 0.0042)")
# Только p=0.001
print("BH FDR=5%:", benjamini_hochberg(pvals, 0.05).sum())
# p_(i) <= 0.05·i/12: i=1:0.0042, i=2:0.0083, i=3:0.0125, i=4:0.0167...
# 0.020 vs 0.0167 → не проходит. Останавливаемся на i=2 (0.008<0.0083).
# Отвергаем 2 гипотезы.Подводные камни
- BH предполагает либо независимость p-value, либо positive regression dependency. Для произвольной зависимости — BH-Yekutieli (логарифмическая поправка), консервативнее.
- Holm-Bonferroni мощнее обычного Bonferroni и тоже контролирует FWER — стандартный выбор.
- FDR — это ожидание доли, не вероятность. Может оказаться, что в конкретном тесте все отвергнутые ложные.
- Если метрики иерархичны (primary, secondary, guardrail) — лучше hierarchical procedure, чем плоский BH/Bonferroni.
- На малых m (2–3) разница между Bonferroni и BH мизерная.
Эталонный ответ
Bonferroni: порог α/m, контроль FWER (≥1 ложного). BH: сортируем, отвергаем все p_(i) ≤ q·i/m начиная сверху, контроль FDR (доли ложных среди отвергнутых). BH мощнее при многих эффектах, Bonferroni строже.