Статистика в биоинформатике: p-value и FDR

Биоинформатика проверяет тысячи гипотез разом — по гену на тест. Без поправки на множественность вы утонете в ложных открытиях.

Проблема множественных сравнений: когда проверяют много гипотез одновременно, часть «значимых» результатов появляется случайно, и сырой p-value перестаёт быть надёжным.

Это, возможно, самый важный статистический урок для биоинформатика. Типичный эксперимент сравнивает экспрессию 20 000 генов между здоровыми и больными. Если для каждого гена смотреть p < 0,05, то даже при полном отсутствии реальных различий ~1000 генов окажутся «значимыми» чисто случайно. Разберём, почему и как с этим бороться. (Базовое понятие p-value — в курсе «Статистика»; здесь — про множественность.)

Откуда берутся ложные открытия

p < 0,05 означает «при отсутствии эффекта такой результат случаен с вероятностью 5%». Один тест — нормально. Но 20 000 тестов при нулевом эффекте дадут в среднем 0,05 × 20000 = 1000 ложноположительных. Покажем масштаб бедствия.

n_genes = 20000
alpha = 0.05
expected_false_positives = n_genes * alpha
print(f'Генов протестировано: {n_genes}')
print(f'Ожидаемых ложных "открытий" при p<0.05: {expected_false_positives:.0f}')

Вывод:

Генов протестировано: 20000
Ожидаемых ложных "открытий" при p<0.05: 1000

Тысяча ложных срабатываний потопит немногие настоящие. Нужна поправка на число тестов.

Поправка Бонферрони: строгая

Самый простой подход: ужесточить порог, поделив его на число тестов. Порог становится α/m. Это контролирует вероятность хоть одной ошибки (FWER), но очень консервативно — отсекает и многое настоящее.

pvals = [0.001, 0.008, 0.02, 0.04, 0.3]
m = len(pvals)
alpha = 0.05
threshold = alpha / m
print(f'Порог Бонферрони: {threshold:.3f}')
for p in pvals:
    verdict = 'значим' if p < threshold else 'нет'
    print(f'  p={p}: {verdict}')

Вывод:

Порог Бонферрони: 0.010
  p=0.001: значим
  p=0.008: значим
  p=0.02: нет
  p=0.04: нет
  p=0.3: нет

С порогом 0,01 проходят лишь два самых сильных результата. Бонферрони почти не ошибается ложно, но теряет реальные находки — слишком строг для геномики.

FDR (Бенджамини-Хохберг): практичная

В геномике обычно контролируют не вероятность хоть одной ошибки, а долю ложных среди отобранных — FDR (False Discovery Rate). Процедура Бенджамини-Хохберга мягче Бонферрони: сортируем p по возрастанию и сравниваем k-й с (k/m)·α.

pvals = [0.001, 0.008, 0.02, 0.04, 0.3]
m = len(pvals)
alpha = 0.05
ranked = sorted(enumerate(pvals), key=lambda x: x[1])
for rank, (idx, p) in enumerate(ranked, start=1):
    threshold = rank / m * alpha
    verdict = 'значим' if p <= threshold else 'нет'
    print(f'  ранг {rank}: p={p}, порог={threshold:.3f} -> {verdict}')

Вывод:

  ранг 1: p=0.001, порог=0.010 -> значим
  ранг 2: p=0.008, порог=0.020 -> значим
  ранг 3: p=0.02, порог=0.030 -> значим
  ранг 4: p=0.04, порог=0.040 -> значим
  ранг 5: p=0.3, порог=0.050 -> нет

FDR пропустил четыре результата вместо двух у Бонферрони — мягче, но честно: мы принимаем, что среди отобранных может быть до 5% ложных. Для геномики, где важно не упустить кандидатов, это золотая середина.

Как работает под капотом: FWER против FDR

Разница в том, что именно контролируем. FWER (Бонферрони) — вероятность хоть одной ошибки во всём наборе; подходит, когда любая ложная находка дорого стоит. FDR — ожидаемая доля ложных среди объявленных значимыми; подходит для разведки, где из сотен кандидатов потом проверяют экспериментально. В геномике почти всегда выбирают FDR: лучше получить список из 200 генов с 5% примеси, чем 5 генов и упустить остальные.

Частые ошибки

  • Смотреть на сырой p при тысячах тестов. Без поправки список «находок» полон случайностей.
  • Всегда брать Бонферрони. В геномике он чрезмерно строг; чаще нужен FDR.
  • Путать «p мало» и «эффект большой». Значимость — не то же, что биологическая важность; смотрите и на величину изменения.

Итог

  • Тестируя тысячи генов, получаешь множество случайно «значимых» — это проблема множественных сравнений.
  • Бонферрони делит порог на число тестов: строго, контролирует любую ошибку, но теряет находки.
  • FDR (Бенджамини-Хохберг) контролирует долю ложных среди отобранных — мягче и практичнее для геномики.
  • Выбор FWER или FDR зависит от цены ложной находки; в геномике обычно FDR.
Проверьте себя
1. В чём суть проблемы множественных сравнений?
AТесты идут слишком медленно
BПри тысячах одновременных тестов часть результатов оказывается значимой случайно
Cp-value невозможно посчитать
DГены мешают друг другу
2. Как работает поправка Бонферрони?
AУвеличивает порог значимости
BДелит порог α на число тестов m, делая критерий строже
CУдаляет половину генов
DСортирует p-value
3. Почему в геномике обычно предпочитают FDR, а не Бонферрони?
AFDR проще считать
BБонферрони слишком строг и теряет реальные находки; FDR контролирует долю ложных и мягче
CFDR всегда даёт меньше результатов
DБонферрони не работает в Python