Подглядывать в A/B-тест и останавливать его на первом «p < 0.05» — самый дорогой способ обмануть самого себя. Если вы зафиксировали размер выборки заранее и посчитали значимость один раз в конце — всё честно, ошибка первого рода держится на заявленных пяти процентах. Но как только вы начинаете смотреть на дашборд каждый день и жать «стоп» при первом зелёном, реальная вероятность объявить победу там, где эффекта нет, вырастает в разы. Хорошая новость: подглядывать можно — просто по другим правилам. Для этого придумали секвенциальные методы: alpha-spending (Pocock, O'Brien-Fleming), mSPRT и always-valid p-values. Ниже разберу, почему наивное подглядывание ломает статистику и как смотреть в тест хоть каждый час, не раздувая ошибку.
Почему остановка на первом «значимо» врёт?
Классический t- или z-тест устроен так: вы заранее решаете, сколько наблюдений собрать, доводите эксперимент до этого числа и только тогда один раз считаете p-value. Порог 0.05 калиброван ровно под этот сценарий — один взгляд на заранее известной выборке. Вся математика «вероятность ошибиться не выше пяти процентов» держится на честном слове, что вы посмотрите ровно один раз.
Подглядывание превращает один тест в серию. Каждый новый взгляд — это ещё одна попытка случайно перепрыгнуть порог за счёт шума. Метрика конверсии гуляет туда-сюда даже при полностью одинаковых вариантах: сегодня B впереди на процент, завтра позади. Если вы даёте себе право остановиться в любой из этих моментов, вы фактически ждёте, пока шум сам не подкинет вам «красивую» картинку. Это тот же эффект множественных сравнений, только сравнения раскиданы не по метрикам, а по времени.
Аналогия простая: подбрасывайте монету и объявляйте её «нечестной» в первый же момент, когда наберётся подозрительная серия орлов. Рано или поздно такая серия выпадет у абсолютно честной монеты — надо только достаточно долго ждать и иметь право остановиться на удобном месте.
Насколько сильно раздувается ошибка первого рода?
Проще один раз увидеть на симуляции, чем поверить на слово. Возьмём A/A-тест — два варианта с одинаковой истинной конверсией 10%, то есть настоящего эффекта нет вообще. Будем «подглядывать» 20 раз по ходу набора выборки и останавливаться, как только классический z-тест покажет значимость:
import numpy as np
from scipy import stats
def peeking_experiment(n_max=10000, looks=20, alpha=0.05):
# A/A: истинной разницы нет
a = np.random.binomial(1, 0.10, n_max)
b = np.random.binomial(1, 0.10, n_max)
checkpoints = np.linspace(n_max // looks, n_max, looks).astype(int)
for n in checkpoints:
pa, pb = a[:n].mean(), b[:n].mean()
pooled = (a[:n].sum() + b[:n].sum()) / (2 * n)
se = np.sqrt(2 * pooled * (1 - pooled) / n)
if se == 0:
continue
z = (pb - pa) / se
p_value = 2 * (1 - stats.norm.cdf(abs(z)))
if p_value < alpha:
return True # «нашли» эффект, которого нет
return False
fpr = np.mean([peeking_experiment() for _ in range(2000)])
print(f"Доля ложных срабатываний: {fpr:.3f}")
Вместо заявленных 0.05 доля ложных срабатываний уходит в район 0.15–0.25, в зависимости от того, как часто вы смотрите. То есть вы «находите» несуществующий эффект в каждом четвёртом-пятом тесте. Чем чаще взгляды, тем хуже: непрерывный мониторинг с остановкой при первом зелёном в пределе почти гарантирует ложную победу, если ждать достаточно долго. Прогоните этот код сами — можно прямо в Python-песочнице, меняя число взглядов и размер выборки, чтобы увидеть, как ошибка ползёт вверх. Это отрезвляет сильнее любого учебника.
Что такое alpha-spending и при чём тут Pocock и O'Brien-Fleming?
Первое честное решение придумали медики в клинических испытаниях, где смотреть на промежуточные результаты нужно по этическим причинам: нельзя месяцами поить пациентов пустышкой, если препарат уже явно работает или явно вредит. Идея называется alpha-spending и звучит так: у вас есть общий бюджет ошибки первого рода — те самые 5% — и вы его распределяете между запланированными взглядами, а не тратите целиком на каждый.
Работает это как групповой секвенциальный дизайн. Вы заранее фиксируете, сколько раз и на каких долях выборки будете смотреть (например, на 25%, 50%, 75% и 100% данных). На каждом взгляде порог значимости не 0.05, а строже — так, чтобы суммарная вероятность хоть раз ошибиться за все взгляды осталась 5%.
Две классические функции распределения бюджета:
- Pocock — тратит альфу примерно поровну на всех взглядах. Пороги на каждом шаге одинаково строгие (грубо, значимость требуется на уровне около 0.02–0.03 вместо 0.05). Удобно, когда вы реально хотите иметь шанс остановиться рано.
- O'Brien-Fleming — на ранних взглядах пороги драконовски строгие (остановиться в самом начале почти нереально), а к финалу они приближаются к обычному 0.05. Логика: ранняя остановка оправдана только при огромном эффекте, зато в конце вы почти не теряете мощность по сравнению с фиксированным тестом.
На практике O'Brien-Fleming чаще выбирают как дефолт: он бережёт мощность и не соблазняет остановиться на первом же шевелении метрики. Минус группового подхода — взгляды нужно планировать заранее, импровизировать «а посмотрю-ка ещё разок» нельзя.
Как работают mSPRT и always-valid p-values?
Групповой дизайн хорош, но требует расписания. В продуктовой аналитике хочется другого: смотреть в дашборд когда угодно и сколько угодно раз, и чтобы вывод оставался честным в любой момент. Это семейство методов называют anytime-valid — «валидные в любой момент времени».
mSPRT (mixture Sequential Probability Ratio Test) — рабочая лошадка этого подхода, её популяризировали внутренние платформы экспериментов у крупных технологических компаний. В основе — отношение правдоподобия: на каждом наблюдении вы сравниваете, насколько данные лучше согласуются с гипотезой «эффект есть» против «эффекта нет». Обычный SPRT требует заранее назвать конкретный размер эффекта, а вы его не знаете. Приставка «mixture» решает это: вместо одного значения эффекта берётся распределение-смесь (по сути, слабый приор на размер эффекта), и по нему усредняется. Получается статистика, которую можно проверять после каждого пользователя, а порог остановки держит ошибку под контролем при любом числе взглядов.
Always-valid p-value — обёртка над той же идеей в привычном формате. Это p-value, устроенное так, что правило «останови тест, если оно опустилось ниже alpha» удерживает ошибку первого рода на уровне alpha независимо от того, когда и сколько раз вы посмотрели. Технически always-valid p-value не растёт со временем в вашу пользу так, как хотелось бы наивно — он заметно консервативнее обычного. Рядом идёт понятие confidence sequence — доверительный интервал, который валиден одновременно во все моменты времени, а не только в одной заранее выбранной точке.
Ключевое отличие от alpha-spending: тут не нужно заранее объявлять расписание взглядов. Останавливайтесь когда угодно — хоть по решению продакта в среду днём. Цена этой свободы — на данных, где эффекта нет или он слабый, тест в среднем идёт дольше, чем фиксированный.
Правда ли секвенциальные тесты ускоряют эксперименты?
И да, и нет — зависит от того, что вы измеряете. Если эффект крупный и настоящий, секвенциальный тест позволяет остановиться сильно раньше запланированного горизонта: сигнал вылезает из шума быстро, и нет смысла добивать выборку до конца. На сильных победителях и явных провалах экономия времени реальная и ощутимая.
Но есть плата. Чтобы сохранить ту же мощность, что и у фиксированного теста, секвенциальному нужен чуть больший максимальный размер выборки. То есть в худшем случае — когда эффект нулевой или на грани — вы можете прогнать даже больше наблюдений, чем при обычном дизайне. Выигрыш идёт по ожидаемому времени остановки, усреднённому по всем возможным исходам, а не по гарантированному сроку каждого конкретного теста.
Отсюда практический вывод: секвенциальные методы окупаются, когда у вас поток экспериментов и часть из них — явные победители или провалы, которые хочется отсекать рано. Если вы гоняете один аккуратный тест на маленьком приросте конверсии, честный фиксированный дизайн с посчитанным заранее размером выборки нередко эффективнее. Не забывайте, что даже статистически значимый результат надо ещё перевести в деньги — прикинуть влияние на выручку и удержание через продуктовые метрики.
Как выбрать метод под свою задачу?
Ориентируюсь по трём вопросам.
Первый: можете ли вы спланировать взгляды заранее? Если да, и запусков немного — берите групповой дизайн с O'Brien-Fleming. Он бережёт мощность и почти не проигрывает фиксированному тесту в финале.
Второй: нужна ли свобода смотреть в любой момент и останавливаться по бизнес-решению? Тогда ваш выбор — anytime-valid: mSPRT или always-valid p-values через готовую библиотеку. Не пишите это руками с нуля — легко ошибиться в порогах.
Третий: а нужен ли вообще секвенциальный тест? Если команда дисциплинированно ждёт конца эксперимента и не дёргает ручку раньше времени, обычный фиксированный дизайн проще, мощнее и понятнее для стейкхолдеров. Секвенциальные методы решают конкретную боль — необходимость подглядывать, — а не являются апгрейдом «просто так».
И общий принцип: метод выбирается до запуска и не меняется по ходу. Начать как фиксированный тест, а в середине передумать и «досчитать по always-valid, раз результат не нравится» — это то же самое подглядывание, только с наукообразным прикрытием.
Что это меняет для аналитика на практике?
Три вещи, которые стоит унести с собой.
Первое — перестаньте смотреть на промежуточную значимость в фиксированном тесте и тем более принимать по ней решения. Если очень надо мониторить (не сломался ли сплит, нет ли утечки данных), смотрите на служебные метрики, а не на p-value целевой. Это стандартный вопрос на собеседованиях, кстати — в тренажёре вопросов про peeking и раздувание ошибки спрашивают регулярно, и «а мы просто дождались, когда стало значимо» — это красный флаг для интервьюера.
Второе — если подглядывание неизбежно по природе процесса (руководство хочет видеть промежуточные итоги), зашейте это в дизайн заранее: alpha-spending или mSPRT. Тогда каждый взгляд честный, и никто не поймает вас на раздутом false positive rate постфактум.
Третье — считайте не только значимость, но и достаточный размер выборки и минимальный детектируемый эффект до старта. Половина проблем с подглядыванием растёт из того, что тест запустили без расчёта и теперь мучительно ждут «хоть какого-то» сигнала. Крепкий фундамент по вероятности и статистике снимает большинство таких вопросов — разобраться в базе помогают практические задачи и разборы реальных ситуаций в кейсах. А выгружать данные для собственных проверок и симуляций удобно связкой SQL плюс Python: срез считаете в SQL-песочнице, а моделируете подглядывание в Python.
Секвенциальные тесты — не магия и не бесплатный ускоритель. Это дисциплина: вы заранее признаёте, что будете смотреть много раз, и заранее платите за это правильным порогом. Наивное «остановлюсь, когда позеленеет» стоит вам каждого четвёртого-пятого ложного вывода — а в продукте это выкаченные фичи, которые ничего не улучшают, и потерянное доверие к экспериментам.
Если хотите системно прокачать A/B-тесты, статистику и SQL под собеседование аналитика — в Pro открыты все 425 SQL и 402 Python-задачи, разборы кейсов и AI-собес без лимитов. Начать можно бесплатно: решить первые задачи в тренажёре и посмотреть, где проседает база.