A/B-тест — это контролируемый эксперимент, а не «сравнение до и после». Случайное распределение пользователей по вариантам в среднем уравнивает все факторы — и те, что вы измеряете, и те, о которых не догадываетесь. Именно поэтому разница средних по целевой метрике даёт несмещённую оценку причинного эффекта1, тогда как наблюдательное сравнение путает эффект изменения с трендом, сезонностью и сменой аудитории.
Что измеряет A/B-тест
Перед запуском фиксируют первичную метрику (OEC, overall evaluation criterion2, 3) — ту единственную величину, по которой принимается решение, — и формулируют гипотезу. OEC должна отражать долгосрочную ценность, а не сиюминутный клик: метрика, которую легко «накрутить» изменением, но которая не связана с удержанием и выручкой, уводит в ложную оптимизацию. Рядом задают guardrail-метрики — показатели, которые изменение не должно ухудшить (скорость загрузки, отток, жалобы), даже если первичная метрика выросла.
Важная техническая тонкость: единица рандомизации должна совпадать с единицей анализа. Если делите по пользователям, а считаете метрику по сессиям или событиям, наблюдения внутри одного пользователя коррелированы, обычная формула дисперсии их недооценивает, а доверительные интервалы оказываются ложно узкими. Это завышает число «значимых» результатов ещё до всякого подглядывания.
Сначала мощность, потом запуск
Тест без достаточной мощности4 не способен обнаружить эффект, даже когда тот
реален: он почти обречён вернуть «не значимо». Поэтому до запуска фиксируют три
величины: уровень значимости (обычно двусторонний α =
5%), мощность (обычно 1 − β = 80%) и
MDE — минимальный эффект, который вообще имеет смысл ловить. MDE —
это бизнес-порог («какой прирост окупит внедрение»), а не «любой ненулевой».
Зависимость размера выборки от MDE обратно-квадратичная: чтобы надёжно поймать вдвое меньший эффект, нужно вчетверо больше наблюдений. Для двух долей размер выборки на вариант считается напрямую:
import numpy as np
from scipy.stats import norm
def sample_size_per_arm(p0, mde_rel, alpha=0.05, power=0.8):
p1 = p0
p2 = p0 * (1 + mde_rel) # MDE как относительный прирост
z_a = norm.ppf(1 - alpha / 2) # двусторонний
z_b = norm.ppf(power)
p_bar = (p1 + p2) / 2
num = (z_a * np.sqrt(2 * p_bar * (1 - p_bar))
+ z_b * np.sqrt(p1 * (1 - p1) + p2 * (1 - p2))) ** 2
return int(np.ceil(num / (p2 - p1) ** 2))
n = sample_size_per_arm(p0=0.05, mde_rel=0.10) # конверсия 5%, MDE +10%
print(f"Нужно ≈ {n:,} наблюдений на вариант") # ≈ 31 234
Если на разумный MDE выборки не хватит за приемлемый срок, тест бессмысленно запускать — это сигнал поменять метрику на более чувствительную, увеличить эффект изменения или снизить дисперсию (см. CUPED ниже), а не «посмотреть, что получится».
Проблема подглядывания
Самая частая и самая дорогая ошибка. Соблазн понятен: дашборд обновляется в
реальном времени, и хочется остановить тест, как только увидел
p < 0.05. Но многократная проверка
накапливающихся данных раздувает вероятность ложного срабатывания: при фиксированном
пороге она уходит далеко за номинальные 5%5. Под нулевой гипотезой (эффекта
нет) z-статистика блуждает случайно и рано или поздно пересечёт порог — «значимость»
гарантирована любому, кто готов ждать и подглядывать.
import numpy as np
from scipy.stats import norm
rng = np.random.default_rng(0)
z_crit = norm.ppf(0.975) # 1.96
def false_positive_rate(n_looks, n_max=10_000, sims=40_000):
step = n_max / n_looks
# под H0 z-статистика на n наблюдениях ~ случайное блуждание / sqrt(n)
blocks = rng.normal(0, np.sqrt(step), size=(sims, n_looks))
z = np.cumsum(blocks, axis=1) / np.sqrt(step * np.arange(1, n_looks + 1))
reject = (np.abs(z) > z_crit).any(axis=1) # остановка на первом p<0.05
return reject.mean()
for k in (1, 5, 20, 89):
print(f"{k:>3} проверок → ложных побед: {false_positive_rate(k):.1%}")
# 1 → 5.1% · 5 → 14.2% · 20 → 25.3% · 89 → 36.9%
Лечится это тремя способами. Первый — фиксированный горизонт: посчитать размер выборки заранее и не принимать решение до его достижения. Второй — последовательный анализ, восходящий к критерию отношения вероятностей Вальда6: групповые последовательные границы Покока7 (равномерно строже на каждой промежуточной проверке) и O’Brien–Fleming8 (очень строго в начале, почти номинальный порог к финалу) корректируют критическое значение так, чтобы суммарная ошибка осталась на уровне 5%. Третий — always-valid p-значения9 (и доверительные интервалы), которые позволяют смотреть на результат сколько угодно часто и останавливаться в любой момент, не раздувая ошибку. Если бизнесу нужен непрерывный мониторинг — это правильный инструмент, а не наивный ежедневный t-тест.
Множество метрик и сегментов
Перебор метрик — та же проблема подглядывания, только по другой оси. Проверяя 20
метрик при α = 5%, вы в среднем получите одну
ложную «значимость» даже при полном отсутствии эффекта. Решения: заранее назначить
одну первичную метрику (а остальные считать диагностическими), либо контролировать
долю ложных открытий (FDR)10 поправкой на множественность.
То же касается сегментов. Если резать данные постфактум — по устройствам, странам, когортам — и искать, «где сработало», что-нибудь «значимое» найдётся всегда: это «сад расходящихся троп». Отдельная ловушка — парадокс Симпсона11: эффект, положительный в каждом сегменте по отдельности, при агрегации может стать отрицательным (и наоборот), если состав групп по сегментам несбалансирован. Поэтому сегментный разрез — инструмент для гипотез к следующему тесту, а не для выводов из текущего; набор сегментов фиксируют до запуска.
Доверять ли результату: читаем интервал
«Победа» — это не факт p < 0.05, а
доверительный интервал прироста. Он сразу отвечает на два вопроса: отличается ли
эффект от нуля и — что важнее — достаточно ли он велик, чтобы окупить внедрение.
Отсюда два правила, которые экономят больше всего ошибочных решений. Статистическая значимость — не то же самое, что практическая. На миллионной выборке «значимым» становится и прирост в 0.2%, который не покрывает стоимость внедрения; поэтому интервал сравнивают с порогом практической значимости, а не только с нулём. И обратное: отсутствие значимости — не доказательство отсутствия эффекта, особенно при недоборе мощности; широкий интервал, накрывающий и ноль, и крупный эффект, означает «данных не хватило», а не «эффекта нет».
Что ломает A/B на практике
Даже корректно спланированный тест может оказаться недействительным. Первое, что
проверяют, — SRM12 (sample ratio mismatch): если деление
задумано как 50/50, а наблюдаемые размеры групп значимо разошлись, значит сломано
само назначение (баг разметки, бот-трафик, перекос редиректов), и любым метрикам
верить нельзя. Простая проверка — критерий χ²:
from scipy.stats import chisquare
def srm_check(n_control, n_treatment, split=(0.5, 0.5)):
total = n_control + n_treatment
observed = [n_control, n_treatment]
expected = [total * split[0], total * split[1]]
stat, p = chisquare(observed, expected)
return p
p = srm_check(50_800, 49_200) # ожидали 50/50
print(f"SRM p-value: {p:.2e}") # ≈ 4e-07 → деление сломано, тест недействителен
Дальше — типовые источники смещения. Метрики-отношения (клики на сессию), когда единица анализа крупнее единицы рандомизации, требуют дельта-метода для корректной дисперсии. Эффекты новизны и привыкания: поведение в первые дни нерепрезентативно — нужно смотреть динамику эффекта, а не только среднее. Интерференция: в соцсетях и маркетплейсах группы влияют друг на друга, и обычный пользовательский A/B смещён — нужен кластерный рандомизированный дизайн. Наконец, чувствительность теста можно повысить без увеличения выборки — метод CUPED13 снижает дисперсию метрики, вычитая предсказуемую часть по данным до эксперимента, и тем сокращает нужный срок при той же мощности.
Чек-лист перед запуском
- Метрика и гипотеза зафиксированы. Одна первичная метрика (OEC) и guardrail-метрики выбраны до старта.
- Мощность посчитана. Известны MDE, α, мощность и вытекающие из них размер выборки и срок.
- Горизонт остановки назначен. Либо фиксированный размер, либо явный метод последовательного анализа — но не «смотрим, пока не станет значимо».
- SRM под контролем. Проверка баланса групп включена в мониторинг.
- План анализа сегментов задан заранее. Разрезы — для гипотез, а не для поиска значимости постфактум.
- Решение принимается по интервалу. Сравнение с порогом практической значимости, а не только с нулём.
Как с этим работает StatGazer
A/B-тест — это не «поделить трафик пополам», а методологический выбор: метрика, мощность, горизонт, дизайн и план анализа. Мы проектируем эксперименты под конкретное решение на стороне бизнес-аналитики, а если тест уже проведён — выполняем его независимую проверку и валидацию: воспроизводим расчёт, проверяем подглядывание, SRM, множественность метрик и границы выводов. Никаких обещаний по исходу здесь нет — задача в том, чтобы решение опиралось на корректный эксперимент, а не на статистический шум. Описать задачу можно в контактах — ответим в течение 24 часов.
Источники
Ключевые работы по дизайну экспериментов, мощности, последовательному анализу и онлайн-A/B, упомянутые в статье. Номера-сноски в тексте ссылаются на этот список.
- Fisher, R. A. (1935). The Design of Experiments (1st ed.). Edinburgh: Oliver & Boyd. en.wikipedia.org. — вводит рандомизацию, повторность и блокирование как основу причинного вывода в эксперименте.
- Kohavi, R., Longbotham, R., Sommerfield, D., & Henne, R. M. (2009). Controlled Experiments on the Web: Survey and Practical Guide. Data Mining and Knowledge Discovery, 18(1), 140–181. doi:10.1007/s10618-008-0114-1. — обзор и практическое руководство по онлайн-A/B; понятие OEC и контроль качества эксперимента.
- Kohavi, R., Tang, D., & Xu, Y. (2020). Trustworthy Online Controlled Experiments: A Practical Guide to A/B Testing. Cambridge: Cambridge University Press. doi:10.1017/9781108653985. — каноническая монография по доверенным онлайн-экспериментам (A/B).
- Cohen, J. (1988). Statistical Power Analysis for the Behavioral Sciences (2nd ed.). Hillsdale, NJ: Lawrence Erlbaum Associates. doi:10.4324/9780203771587. — справочник по мощности, размерам эффекта и расчёту необходимого размера выборки.
- Armitage, P., McPherson, C. K., & Rowe, B. C. (1969). Repeated Significance Tests on Accumulating Data. Journal of the Royal Statistical Society: Series A, 132(2), 235–244. doi:10.2307/2343787. — показывает инфляцию ошибки I рода при повторных проверках накапливающихся данных — теория «подглядывания».
- Wald, A. (1945). Sequential Tests of Statistical Hypotheses. Annals of Mathematical Statistics, 16(2), 117–186. doi:10.1214/aoms/1177731118. — последовательный критерий отношения вероятностей (SPRT) — фундамент последовательного анализа.
- Pocock, S. J. (1977). Group Sequential Methods in the Design and Analysis of Clinical Trials. Biometrika, 64(2), 191–199. doi:10.1093/biomet/64.2.191. — групповые последовательные границы с равномерной корректировкой уровня значимости.
- O'Brien, P. C., & Fleming, T. R. (1979). A Multiple Testing Procedure for Clinical Trials. Biometrics, 35(3), 549–556. doi:10.2307/2530245. — консервативные границы O’Brien–Fleming: строго в начале, почти номинальный порог к финалу.
- Johari, R., Koomen, P., Pekelis, L., & Walsh, D. (2017). Peeking at A/B Tests: Why It Matters, and What to Do About It. KDD ’17, 1517–1525. doi:10.1145/3097983.3097992. — always-valid p-значения против подглядывания при непрерывном мониторинге A/B.
- Benjamini, Y., & Hochberg, Y. (1995). Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing. Journal of the Royal Statistical Society: Series B, 57(1), 289–300. doi:10.1111/j.2517-6161.1995.tb02031.x. — контроль доли ложных открытий (FDR) при множественной проверке метрик.
- Simpson, E. H. (1951). The Interpretation of Interaction in Contingency Tables. Journal of the Royal Statistical Society: Series B, 13(2), 238–241. doi:10.1111/j.2517-6161.1951.tb00088.x. — парадокс Симпсона: разворот направления эффекта при агрегации или сегментации данных.
- Kohavi, R., Deng, A., Frasca, B., Walker, T., Xu, Y., & Pohlmann, N. (2013). Online Controlled Experiments at Large Scale. KDD ’13, 1168–1176. doi:10.1145/2487575.2488217. — A/B-эксперименты в масштабе; контроль качества и диагностика sample ratio mismatch (SRM).
- Deng, A., Xu, Y., Kohavi, R., & Walker, T. (2013). Improving the Sensitivity of Online Controlled Experiments by Utilizing Pre-Experiment Data. WSDM ’13, 123–132. doi:10.1145/2433396.2433413. — метод CUPED: снижение дисперсии метрик с помощью данных до эксперимента.