Собесов

Сценарий A/B: Bonferroni vs Benjamini-Hochberg

A/B-тестыMultiple testingСредняяMiddle

Условие

В тесте 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 гипотезы.

Подводные камни

  1. BH предполагает либо независимость p-value, либо positive regression dependency. Для произвольной зависимости — BH-Yekutieli (логарифмическая поправка), консервативнее.
  2. Holm-Bonferroni мощнее обычного Bonferroni и тоже контролирует FWER — стандартный выбор.
  3. FDR — это ожидание доли, не вероятность. Может оказаться, что в конкретном тесте все отвергнутые ложные.
  4. Если метрики иерархичны (primary, secondary, guardrail) — лучше hierarchical procedure, чем плоский BH/Bonferroni.
  5. На малых m (2–3) разница между Bonferroni и BH мизерная.

Эталонный ответ

Bonferroni: порог α/m, контроль FWER (≥1 ложного). BH: сортируем, отвергаем все p_(i) ≤ q·i/m начиная сверху, контроль FDR (доли ложных среди отвергнутых). BH мощнее при многих эффектах, Bonferroni строже.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти