В перформанс-маркетинге скорость тестирования — конкурентное преимущество. В сценарии с частотным A/B тестом ты ждёшь две недели, пока сформируется доверительный интервал, а бюджет кампании за это время сгорает. Байесовский подход даёт тебе обновлённое апостериорное распределение каждый день — даже до завершения теста можешь сказать «вариант B выигрывает с вероятностью 73 %». Эта статья разбирает механику Байесовского A/B теста, правила последовательного принятия решений и динамику размера выборки. Ты отказываешься от фиксированного горизонта частотного метода и переходишь на непрерывное обновление решений в потоке ежедневных данных.
Проблема фиксированного горизонта в частотном тестировании
Классический A/B тест построен на p-value и фиксированном размере выборки. Ты начинаешь с плана вроде «нужно n=5000 посетителей, это займёт 14 дней» и до 14-го дня не принимаешь никакого решения. В течение этого периода ты отправляешь трафик проигрывающему варианту — даже если его коэффициент конверсии на 2 пункта ниже, ты вынужден ждать, не нарушая план теста. Если остановиться раньше, inflates Type I error, возникает проблема множественного тестирования.
В частотном контексте порог p < 0,05 даёт статистическую значимость, но на практике часто встречаются случаи «значимый, но бесполезный» лифт. Например, lift в 0,5 % может быть статистически значимым (благодаря большому размеру выборки), но не иметь практического эффекта. Ширина доверительного интервала и размер эффекта нужно интерпретировать отдельно — частотная логика это не выявляет автоматически.
Другое ограничение: sequential monitoring невозможен. Ты вычисляешь размер выборки в начале, ждёшь, пока накопится этот объём. Если один из вариантов явно выигрывает на промежуточном этапе, ты всё равно продолжаешь — нарушение плана теста делает p-value недействительным.
Байесовский тест: обновлённое апостериорное распределение
Байесовский подход работает по логике: prior belief + данные = posterior. В начале теста ты определяешь априорное распределение коэффициента конверсии каждого варианта (обычно неинформативное Beta(1,1) или информативное на основе исторических данных). При каждом посещении Байесова теорема обновляет posterior. На 100-м посетителе posterior имеет одно состояние, на 200-м — другое. Обновление непрерывное.
Апостериорное распределение точно показывает «вероятностную плотность истинного коэффициента конверсии этого варианта». Например, Beta(25, 75) posterior указывает, что конверсия между 20 % и 30 % имеет высокую вероятностную плотность. Сравнивая posteriori двух вариантов, ты вычисляешь «вероятность того, что B лучше A» — в Байесовском мире эта формула P(B > A) естественна.
Байесовская версия sequential теста: обновляй posterior каждый день, если P(B > A) > 0,95 — остановись и признай B победителем. Этот порог определяется твоей терпимостью к риску — вместо 95 % можешь использовать 90 % или 99 %. В частотном методе нет такого механизма; решение вне фиксированного горизонта не определено. В Байесовском методе решение можешь принять в любой момент — posterior даёт полную информацию.
В Байесовском тесте нет p-value. Вместо этого метрики: probability of superiority (P(B > A)), expected loss (ожидаемый лифт, который теряешь, если выберешь A вместо B), credible interval (95 % диапазон апостериорного распределения). На практике они нагляднее — «вариант B выигрывает в 85 % случаев и при выигрыше даёт средний лифт 2,3 %».
Код обновления posterior
import numpy as np
from scipy.stats import beta
# Априор: Beta(1,1) = uniform
prior_alpha, prior_beta = 1, 1
# Данные: вариант A — 50 конверсий, 200 посещений
conversions_A = 50
visits_A = 200
failures_A = visits_A - conversions_A
# Posterior: Beta(alpha + conversions, beta + failures)
post_alpha_A = prior_alpha + conversions_A
post_beta_A = prior_beta + failures_A
# Выборка из апостериорного распределения
samples_A = beta.rvs(post_alpha_A, post_beta_A, size=10000)
# Вариант B — то же самое
conversions_B = 60
visits_B = 200
failures_B = visits_B - conversions_B
post_alpha_B = prior_alpha + conversions_B
post_beta_B = prior_beta + failures_B
samples_B = beta.rvs(post_alpha_B, post_beta_B, size=10000)
# Вычисли P(B > A)
prob_B_wins = (samples_B > samples_A).mean()
print(f"P(B > A): {prob_B_wins:.2%}") # Пример: 0.82 = B выигрывает в 82 %
Динамический размер выборки и ранняя остановка
В Байесовском тесте размер выборки не фиксирован. Ты можешь установить нижний предел (например, «минимум 1000 посещений», чтобы posterior не был слишком широким), но верхний предел динамический. Как только P(B > A) > 0,95 — тест останавливается. Это может произойти на 500-м посещении или на 5000-м.
Expected loss — отличная метрика для раннего принятия решения. Формула: E[Loss] = E[max(0, CR_winner - CR_chosen)]. Если выбираешь A, но B реально лучше, ожидаемый лифт в конверсии, который теряешь. Устанавливаешь порог, например «ELoss < 0,5 %», и говоришь: «даже в худшем случае потеряю максимум 0,5 % лифта». Такая метрика облегчает консервативное принятие решений.
Пример правила последовательной остановки:
| Метрика | Порог | Действие |
|---|---|---|
| P(B > A) | > 0,95 | Объявить B победителем |
| P(A > B) | > 0,95 | Объявить A победителем |
| ELoss | < 0,005 | Закрыть проигрывающий вариант |
| Минимум посещений | < 1000 | Принимать решение не рано |
Благодаря этим правилам длительность теста сокращается в среднем на 30–40 % (согласно данным Google Optimize и VWO). При большом размере эффекта можешь принять решение с 95 % доверием за 3 дня — вместо 14 дней в частотном методе.
Отличие от multi-armed bandit: Байесовский A/B тест всё ещё не оптимизирует распределение трафика (exploration-exploitation), только обновляет posterior и применяет stopping rule. Алгоритм bandit перераспределяет трафик динамически (например, Thompson Sampling) — побеждающему варианту идёт больше. Байесовский тест сохраняет фиксированное разбиение (50/50), но заканчивается быстро. Bandit агрессивнее — на каждый impression предпочитает побеждающий вариант. Байесовский тест консервативнее — разбиение постоянно, только решение принимается быстро.
Информативный prior и тест incrementality
Выбор prior — самый критичный пункт в Байесовском тесте. Неинформативный prior (Beta(1,1)) игнорирует прошлые знания, posterior полностью data-driven. Информативный prior происходит из исторических данных тестов или базовой конверсии по сегментам. Если среднее за последние 50 тестов на мобильных — 12 % конверсии, можешь использовать Beta(60, 440) prior (примерно 12 % среднее, но с разбросом). Этот prior даёт новому тесту «разумное предположение на основе прошлого».
Преимущество информативного prior: требуемый размер выборки меньше. Posterior обновляется не с нуля, а с обоснованной стартовой позиции. Недостаток: неправильный prior создаёт смещение. Если сегмент изменился или есть сезонный эффект, старый prior вводит в заблуждение. Поэтому нужен анализ чувствительности prior — проверить, меняются ли результаты теста при разных priori.
В процессах оптимизации коэффициента конверсии Байесовский тест упрощает измерение incrementality. Для incrementality нужна контрольная группа или geo-split. Байесовский подход: сравни aposterior коэффициента конверсии контрольной группы с группой теста — получишь распределение лифта. Вместо классического t-test вычисляешь P(lift > 0) — интерпретируется проще. Например: «новая кампания вероятно даёт incrementality в 78 %, ожидаемый лифт 1,2–2,8 %».
Сравнение выбора prior
# Неинформативный prior
prior_uninf = beta(1, 1)
# Информативный prior: исторических 12 % конверсии, n=500 sample
# Beta mean = alpha / (alpha + beta) → 60/500 = 0,12
prior_inf = beta(60, 440)
# 20 конверсий, 100 посещений → posterior
conversions, visits = 20, 100
post_uninf = beta(1 + conversions, 1 + (visits - conversions))
post_inf = beta(60 + conversions, 440 + (visits - conversions))
# Средние значения posterior
print(f"Неинформативный posterior mean: {post_uninf.mean():.2%}") # ~20 %
print(f"Информативный posterior mean: {post_inf.mean():.2%}") # ~13,3 %
Неинформативный prior на малых выборках очень чувствителен к данным, информативный prior регуляризирует на основе истории.
Компромисс: Байесовский тест vs Частотный vs Bandit
Байесовский тест оптимален не для всех сценариев. Частотный тест предпочтителен в регулируемых секторах (медицина, финансы), где p-value — стандарт и процессы peer-review на нём построены. Выбор prior в Байесовском методе может показаться субъективным. Если регуляция требует p-value и время теста фиксировано (например, 30-дневный period обязателен), частотная логика разумнее.
Алгоритмы bandit (Thompson Sampling, UCB) автоматически уравновешивают exploration-exploitation, динамически оптимизируют распределение трафика. Для долгих тестов (3+ недели) bandit превосходит Байесовский A/B тест — отправляет меньше трафика проигрывающему варианту. На коротких тестах (1–2 недели) Байесовский A/B достаточен — регret minimization от bandit'а даёт минимальный прирост за короткий срок.
При очень малых размерах выборки (например, 100 посещений в день) ни Байесовский, ни частотный метод не помогает. Апостериорное распределение слишком широко, P(B > A) никогда не достигает 95 %. В таком случае используй микроконверсии (клик, добавление в корзину — события чаще) или geo-агрегированное тестирование. Байесовский метод не дарует магическое улучшение при малых данных, только даёт интерпретируемый output.
Истинная мощь Байесовского теста: оркестрация cross-channel тестов. Ты проводишь тест креатива в paid-канале, одновременно CRO тест на landing page. Апостериоры обоих тестов можешь объединить (joint posterior), разделить вклад лифта. В частотном методе для этого нужен сложный ANOVA, в Байесовском — MCMC естественно справляется.
Практическое применение: платформы и инструментарий
Google Optimize (сервер закрыт) использовал Байесовский движок. Сейчас для открытого исходного кода есть Python bayesian-testing или R `bayes