Как устроен A/B-тест: от гипотезы до решения
«Расскажите, как вы запустили бы A/B-тест новой кнопки» — вопрос, который проверяет не статистику, а дисциплину.
A/B-тест — это контролируемый эксперимент, в котором пользователей случайно делят на группы, показывают им разные версии продукта и сравнивают целевую метрику. Случайность деления — единственное, что превращает наблюдаемую разницу в вывод о причине.
Вопрос 1. Из чего состоит A/B-тест?
Что проверяет интервьюер. Назовёте ли вы шаги до запуска. Кандидат, который начинает с «делим пополам и смотрим конверсию», сразу выдаёт отсутствие практики: половина работы делается до того, как эксперимент включили.
- Гипотеза. Формулируется как «изменение X приведёт к изменению метрики Y на Z% у сегмента S, потому что …». Без «потому что» это не гипотеза, а догадка.
- Целевая метрика — одна. Плюс метрики-гардрейлы, которые не должны просесть, и диагностические метрики для объяснения результата.
- MDE (minimum detectable effect) — минимальный эффект, который бизнесу важно заметить. Задаётся до теста и определяет размер выборки.
- Размер выборки и длительность — считаются заранее, фиксируются письменно.
- Единица рандомизации — пользователь, сессия, устройство, город.
- Запуск и A/A-проверка — убедиться, что до изменения группы неразличимы.
- Анализ ровно в срок и решение: катим, откатываем, повторяем.
Вопрос 2. Что выбрать единицей рандомизации?
Ошибка здесь ломает эксперимент целиком, поэтому вопрос любят.
| Единица | Когда подходит | Риск |
| Пользователь (user_id) | стандарт: изменения интерфейса, цены | нужен стабильный идентификатор между устройствами |
| Сессия | только для изменений в рамках одного визита | один человек увидит обе версии — опыт «скачет», метрики удержания невалидны |
| Устройство (cookie) | анонимные пользователи, лендинги | один человек = несколько устройств → «протечка» между группами |
| Кластер (город, магазин, компания) | когда есть сетевой эффект или общий контекст | эффективный размер выборки — число кластеров, а не пользователей |
Главное правило: единица рандомизации должна совпадать с единицей анализа. Если делите по пользователям, а считаете конверсию по сессиям, дисперсия окажется занижена и p-value — оптимистичным. Формально это называется нарушением независимости наблюдений.
Вопрос 3. Зачем нужен A/A-тест?
A/A — это тот же эксперимент, но обе группы получают одну и ту же версию. Разницы быть не должно, и именно поэтому он ценен: он проверяет инфраструктуру, а не продукт.
- Работает ли сплитование: 50/50 ли реально делятся пользователи и стабильно ли назначение группы.
- Нет ли SRM (sample ratio mismatch) — расхождения ожидаемой и фактической пропорции групп. Если ждали 50/50, а получили 50.8/49.2 на сотнях тысяч пользователей, это не случайность, а баг: часть трафика теряется, боты попадают в одну группу, редирект ломает сессии. Тест с SRM интерпретировать нельзя — его чинят и перезапускают.
- Совпадают ли предэкспериментальные метрики: если группы уже до изменения различаются по среднему чеку, рандомизация сломана.
Проверка SRM делается критерием хи-квадрат, но на собеседовании достаточно показать логику: считаем, насколько маловероятно получить такое расхождение при честном делении.
import math
def srm_check(n_a, n_b, expected=0.5):
n = n_a + n_b
exp_a, exp_b = n * expected, n * (1 - expected)
chi2 = (n_a - exp_a) ** 2 / exp_a + (n_b - exp_b) ** 2 / exp_b
z = math.sqrt(chi2)
p = 2 * (1 - 0.5 * (1 + math.erf(z / math.sqrt(2))))
return round(chi2, 2), round(p, 5)
print("50 100 / 49 900:", srm_check(50100, 49900))
print("50 800 / 49 200:", srm_check(50800, 49200))
Вывод:
50 100 / 49 900: (0.4, 0.52709)
50 800 / 49 200: (25.6, 0.0)
Первое расхождение объясняется случайностью, второе — нет: p-value фактически ноль, значит в сплитовании баг. Разница между группами при этом составляет меньше процента — на глаз её не заметить, и в этом ценность формальной проверки.
Вопрос 4. Сколько держать тест?
Минимум — полные недельные циклы. Поведение в понедельник и в субботу разное, и тест длиной в четыре дня измерит не эффект, а день недели. Останавливать тест раньше запланированного срока нельзя (об этом — отдельный урок про подглядывание), а тянуть его месяцами тоже плохо: накапливаются посторонние изменения продукта, сезонность и эффект новизны.
Эффект новизны — отдельная ловушка: первые дни пользователи реагируют на сам факт изменения, а не на его пользу. Поэтому у долгоживущих фич смотрят динамику эффекта по неделям, а не только итоговую цифру.
Типичные ошибки кандидатов
- Начинают с «поделим трафик пополам», пропуская гипотезу, метрику и расчёт выборки.
- Называют пять целевых метрик — тогда какая-нибудь «выстрелит» случайно.
- Рандомизируют по сессиям при тесте, влияющем на возвращаемость.
- Не знают про SRM и не проверяют размеры групп перед анализом.
- Останавливают тест через три дня «потому что уже видно».
Как ответить кратко
«Начинаю с гипотезы вида "изменение приведёт к росту метрики на столько-то, потому что…". Выбираю одну целевую метрику и набор гардрейлов, задаю MDE и по нему считаю нужный размер выборки и длительность — обязательно кратно неделям. Рандомизирую по пользователю, а не по сессии, и слежу, чтобы единица рандомизации совпадала с единицей анализа. Перед анализом проверяю SRM: если фактическое деление отличается от 50/50 сильнее, чем допускает случайность, в сплитовании баг и тест надо перезапускать. Останавливаю ровно в запланированный срок и смотрю не только целевую метрику, но и гардрейлы».