Размер выборки, мощность и подводные камни
Вопросы уровня senior: сколько пользователей нужно, что такое мощность и почему нельзя подглядывать в результаты.
Мощность теста — вероятность обнаружить эффект заданного размера, если он действительно есть. Стандарт индустрии — 80%: каждый пятый реальный эффект такой тест всё равно пропустит.
Вопрос 1. Как посчитать нужный размер выборки?
Что проверяет интервьюер. Понимаете ли вы, что размер выборки — это не «сколько наберётся», а следствие четырёх заранее заданных величин: базовой конверсии, MDE, α и мощности.
import math
def sample_size(baseline, mde_abs, alpha_z=1.96, power_z=0.84):
# mde_abs — минимальный улавливаемый эффект в абсолютных долях (0.01 = 1 п.п.)
p = baseline
return math.ceil(2 * (alpha_z + power_z) ** 2 * p * (1 - p) / mde_abs ** 2)
print("Базовая 10%, ловим +1 п.п. :", sample_size(0.10, 0.01), "на группу")
print("Базовая 10%, ловим +2 п.п. :", sample_size(0.10, 0.02), "на группу")
print("Базовая 10%, ловим +0.5 п.п.:", sample_size(0.10, 0.005), "на группу")
Вывод:
Базовая 10%, ловим +1 п.п. : 14112 на группу
Базовая 10%, ловим +2 п.п. : 3528 на группу
Базовая 10%, ловим +0.5 п.п.: 56448 на группу
Ключевая зависимость: MDE входит в знаменатель в квадрате. Уменьшили искомый эффект вдвое — выборка выросла вчетверо. Отсюда самый практичный вывод для продуктовой команды: ловить эффект в 0.5 п.п. на трафике в тысячу человек в день невозможно, и об этом лучше сказать до запуска, а не после месяца ожидания.
Числа 1.96 и 0.84 — это квантили нормального распределения для α = 0.05 (двусторонний) и мощности 80%. Если поднять мощность до 90%, второе число станет 1.28 и выборка вырастет примерно на треть.
Вопрос 2. Почему нельзя подглядывать в результаты?
Это любимый вопрос на позиции уровня middle+ и самая распространённая реальная ошибка в компаниях. Суть: если проверять значимость каждый день и останавливать тест, как только p-value впервые опустилось ниже 0.05, реальная доля ложных срабатываний перестаёт быть 5%.
Причина в том, что p-value гуляет случайным образом. При достаточном числе проверок оно рано или поздно случайно нырнёт под порог — даже когда никакого эффекта нет. При ежедневных проверках в течение двух недель доля ложных выводов вырастает примерно втрое, до 15–20%. Формально это то же самое, что множественные сравнения, только сравнения идут во времени.
Что делать:
- Зафиксировать срок до запуска и смотреть результат один раз в конце — самый простой и надёжный вариант.
- Если останавливать досрочно необходимо, использовать методы, которые это учитывают: групповые последовательные границы (O'Brien–Fleming, Pocock) или всегда валидный вывод (always valid inference) на основе последовательных тестов.
- Смотреть на дашборд эксперимента ежедневно можно — но только на гардрейлы и технические метрики, чтобы поймать поломку, а не на целевую метрику для принятия решения.
Вопрос 3. Множественные сравнения
Та же проблема в пространстве вместо времени: чем больше метрик и срезов вы проверяете, тем выше шанс, что хоть где-то «выстрелит» случайность.
alpha = 0.05
for k in (1, 5, 10, 20, 50):
fwer = 1 - (1 - alpha) ** k
print(f"Проверок: {k:>2} → шанс хотя бы одной ложной тревоги: {round(100 * fwer, 1)}%")
Вывод:
Проверок: 1 → шанс хотя бы одной ложной тревоги: 5.0%
Проверок: 5 → шанс хотя бы одной ложной тревоги: 22.6%
Проверок: 10 → шанс хотя бы одной ложной тревоги: 40.1%
Проверок: 20 → шанс хотя бы одной ложной тревоги: 64.2%
Проверок: 50 → шанс хотя бы одной ложной тревоги: 92.3%
Двадцать метрик — и вероятность найти «победу» на пустом месте выше двух третей. Именно так рождаются отчёты вида «в целом эффекта нет, но у пользователей Android старше 35 из Казани конверсия выросла на 12%».
Способы борьбы:
- Поправка Бонферрони: делим α на число сравнений. Просто, но слишком строго — мощность падает.
- Метод Бенджамини — Хохберга контролирует долю ложных открытий (FDR) и на практике удобнее при десятках метрик.
- Дисциплина: заранее объявить одну целевую метрику; все срезы считать разведкой, а не выводом. Найденный в срезе эффект — это гипотеза для следующего теста, а не результат текущего.
Вопрос 4. Ещё три подводных камня
- Парадокс Симпсона. Вариант B выигрывает в каждом сегменте по отдельности, но проигрывает в целом — из-за разного распределения сегментов между группами. Признак того, что рандомизация или трафик неоднородны.
- Сетевые эффекты. В соцсети или маркетплейсе группы влияют друг на друга: скидка у продавца из группы B забирает покупателей у группы A. Обычная рандомизация по пользователю даёт смещённую оценку — нужен кластерный или switchback-дизайн.
- Дисперсия тяжёлых метрик. Выручка на пользователя имеет огромную дисперсию из-за крупных покупателей, поэтому тесты по ней требуют выборок в разы больше. Стандартные лекарства — CUPED (снижение дисперсии по предэкспериментальным данным), винзоризация и переход на более «лёгкие» метрики вроде конверсии в покупку.
Типичные ошибки кандидатов
- Не знают, что размер выборки растёт квадратично при уменьшении MDE.
- Считают подглядывание безобидным: «мы же просто смотрим».
- Перебирают срезы после теста и объявляют находку результатом.
- Путают мощность и уровень значимости.
- Тестируют выручку на пользователя, не понимая, почему теста «не хватает».
Как ответить кратко
«Размер выборки считается из четырёх величин: базовой конверсии, MDE, α и мощности. MDE входит в формулу в квадрате, поэтому уменьшение искомого эффекта вдвое требует вчетверо больше пользователей — при слабом трафике маленькие эффекты просто недостижимы. Мощность 80% значит, что каждый пятый реальный эффект тест всё равно пропустит. Подглядывать нельзя: многократные проверки одной метрики поднимают долю ложных срабатываний с 5% примерно до 15–20%, потому что p-value случайно колеблется и рано или поздно нырнёт под порог. Если досрочная остановка нужна, беру последовательные границы или always valid inference. То же с множественными метриками: двадцать проверок дают более 60% шанса ложной находки, поэтому целевая метрика одна, а срезы — это гипотезы для следующего теста, а не выводы».