Симулятор A/B-тестов: тысячи виртуальных тестов с известной истиной показывают, как часто тест находит настоящий эффект, сколько ложных побед дают A/A-тест, подглядывание и 20 метрик и насколько «победа» завышает прирост — проклятие победителя. Пять сценариев, путь p-value одного теста, CSV и код.
Цифры остаются в браузере и никуда не отправляются
При нескольких метриках эффекта нет ни в одной — B равна A.
Прогонов
зерно 1 · 1 000 тестов
α = 0,05 · двусторонняя проверка
Уровень значимости α
Выбирайте, только если заранее решили, что B не может быть хуже, и отрицательный результат вас не интересует.
Тест находит эффект в 82 % случаев.
Мощность достаточная. Среди «побед» средний наблюдаемый прирост — +16,9 %, в 1,1 раза больше истинного: это проклятие победителя.
Доля побед — мощность
81,5 %
815 из 1 000
Истинный эффект
+15,0 %
2,00 → 2,30 %
Средний прирост среди побед
+16,9 %
завышен в 1,1 раза
Посетителей на группу
37 800
2 700 × 14 дней
Проверок за тест
1
в конце
Метрик
1
одна основная
02
Наблюдаемый прирост во всех тестах
Наблюдаемый прирост во всех тестах
Красное — тесты, признанные значимыми; пунктир — истинный эффект
03
Один тест по дням
Один тест по дням
p-value после каждого дня; ниже красной линии — «значимо»
В этом тесте p-value опустилось ниже α на 11-й день и осталось там к концу теста.
04
Проверить в Python / R
Проверить в Python / R
import numpy as np
from scipy import stats
rng = np.random.default_rng(1)
pa, pb, per_day, days, runs = 0.02, 0.023, 2700, 14, 1000
def z(a, b, n):
p = (a + b) / (2 * n)
return (b - a) / n / np.sqrt(p * (1 - p) * 2 / n)
# одна проверка в конце: доля побед и проклятие победителя
n = per_day * days
a = rng.binomial(n, pa, runs)
b = rng.binomial(n, pb, runs)
win = np.abs(z(a, b, n)) > stats.norm.ppf(0.975)
up = b / a - 1
print(win.mean(), up[win & (up > 0)].mean())
05
Сценарии
06
Частые вопросы
Чтобы увидеть, как часто тест ошибается при ваших параметрах. Тысяча виртуальных тестов с известной истиной считается за доли секунды и показывает мощность, долю ложных побед и цену подглядывания. Формулы говорят то же самое, но гистограмма тысячи результатов убеждает быстрее: видно, насколько по-разному выглядит один и тот же эффект.
Тест двух одинаковых версий. В симуляторе это сценарий «эффекта нет»: при α = 0,05 около 5 % тестов всё равно покажут «значимую» разницу — на 10 000 прогонов выходит 5,0 %. В жизни A/A-тест проверяет, что деление трафика и подсчёт метрик работают: заметно больше 5 % побед или перекос групп — повод искать ошибку.
Среди тестов, признанных значимыми, наблюдаемый прирост систематически больше истинного: проходят те, кому повезло с шумом. При мощности 82 % завышение небольшое — 17,0 % вместо 15 %. Маленький тест на маленький эффект находит его в 6 % случаев, и среди этих «побед» средний прирост — 44,5 % вместо 5 %, почти в девять раз больше.
p < 0,05 случается и без эффекта — в 5 % тестов, это цена порога. Дальше доля растёт от того, как тест ведут: проверка каждый день в течение 28 дней даёт около 28 % ложных побед, 20 метрик без поправки — 64 %. Симулятор показывает все три случая на одних и тех же параметрах.
Это мощность. Если выборка рассчитана под эффект, около 80 %: сценарий «правильный тест» — +15 % при 2 700 посетителях в день на группу за 14 дней — находит эффект в 82 % прогонов. Тест на +5 % при 300 в день за те же 14 дней находит его в 6 % случаев — почти так же редко, как ложную победу.
Одному правильно спланированному — в целом да: выборка рассчитана заранее, смотрели один раз в конце, основная метрика одна. Но даже такой тест в 5 % случаев находит эффект, которого нет, и завышает настоящий. Важные решения стоит подтверждать повторным тестом или наблюдением после выкатки.