Sequential testing простыми словами

Проверь себя · 1/3разбор после ответа
Что именно посчитает выражение SUM(amount) OVER (PARTITION BY campaign_id ORDER BY event_time) в таблице платежей по кампаниям?

Зачем это знать

Классика A/B: «зафиксируй выборку заранее, не подглядывай в середине». Но это медленно и неоптимально: если эффект огромный, зачем ждать ещё неделю?

Sequential testing — семейство методов, которые позволяют остановить эксперимент раньше и сохранить валидность. Используется в Netflix, Google, Microsoft.

На собесах middle+ в крупных компаниях часто спрашивают: «как безопасно подглядывать?».

Короткое объяснение

В обычном A/B: проверяем p-value один раз в конце. Если проверять много раз — частота ложноположительных растёт (p-hacking).

Sequential testing корректирует множественные проверки → можно смотреть на метрику и останавливаться раньше.

Проблема «подглядывания»

Стандартный t-тест с α = 0.05:

  • 1 проверка: частота ложноположительных 5%
  • 5 проверок: ~14%
  • 10 проверок: ~19%
  • Каждый день: стремится к 100% со временем

«Подглядывать и останавливать при p < 0.05» — способ гарантированно найти «значимость» на пустом месте.

Методы sequential testing

1. Always Valid Inference (AVI)

Специальные p-values, которые валидны в любой момент теста, сколько бы раз ни проверяли.

p_AVI(t) = min(p(t), 1)

Формула учитывает множественные «подглядывания». Реализация сложная, но есть библиотеки.

2. SPRT (Sequential Probability Ratio Test)

Отношение правдоподобия (log-likelihood ratio) проверяется после каждого наблюдения. Остановка, когда выходит за границы.

Подход предложен Вальдом ещё в 1940-х.

3. Alpha spending

Разделить α на «бюджеты» для каждой проверки. Например, 5 проверок → по α = 0.01 на каждую (на практике делится сложнее — используются правила Lan-DeMets).

4. mSPRT (mixture SPRT)

Универсальный байесовский подход. Оптимизирован для практических A/B.

Пример: mSPRT

# Pseudo-code (упрощённо)
from sequential_testing import mSPRT

test = mSPRT(alpha=0.05, beta=0.2)

for each_day:
    new_data = fetch_yesterday()
    test.update(new_data)
    
    if test.reject_null():
        print("Stop — lift detected")
        break
    if test.accept_null():
        print("Stop — no lift")
        break

Компромиссы

Плюсы

  • Быстрее останавливаете очевидно плохие или очевидно хорошие тесты
  • Экономия времени и ресурсов
  • Меньше пользователей под плохим вариантом

Минусы

  • Сложнее в реализации
  • Требует дисциплины — нельзя «смешивать» правила остановки
  • На малых эффектах всё равно долго
Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Когда использовать

  • Много экспериментов (нужно быстрее)
  • Высокий трафик (данные копятся быстро)
  • Ограниченное время на тест

Когда НЕ нужно

  • Мало экспериментов (проще обычный тест)
  • Эффект новизны (нужно дождаться стабилизации)
  • Сезонные эффекты

Реализация в компаниях

Netflix — Quasi-Experimentation

Использует causal inference + sequential методы.

Optimizely — Stats Engine

Коммерческое решение на основе AVI.

Open source

abtest, sprtt, confseq — Python-пакеты для sequential A/B.

На собесе

«Что такое sequential testing?» Методы, которые позволяют безопасно останавливать A/B раньше срока.

«Почему нельзя подглядывать в обычном тесте?» Частота ложноположительных растёт с каждой проверкой.

«Как корректирует?» Alpha spending, log-likelihood ratio, always-valid p-values.

«Когда использовать?» Высокий трафик и много экспериментов.

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

Смешивать правила остановки

Если запустили как sequential, нельзя в середине переключиться на «дождусь полного N».

Игнорировать эффект новизны

Ранняя остановка может пропустить стабилизацию метрики после первых дней.

Мало данных

Для sequential нужно быстрое накопление — на сервисах с низким трафиком не работает.

Связанные темы

FAQ

Всегда безопаснее?

Только если правильно реализован. Неправильный sequential test хуже обычного.

Лучше Bayesian?

Bayesian A/B — другой подход, тоже позволяет подглядывать. Но требует априорное распределение (prior).

Open source?

confseq для Python. peek_ab для R.