Большинство аналитиков воспринимают A/B-тест как «сравнить средние двух групп». Это описание механики, но не сути. Суть — в каузальности: этот эффект вызван нашим изменением, а не чем-то ещё?
Пользователи, видевшие промо-баннер, покупают чаще. Это не значит, что баннер увеличивает покупки — возможно, промо показывается активным пользователям, которые и так бы купили. Без рандомизации мы не отличим эффект баннера от эффекта отбора.
A/B-тест решает эту проблему: рандомизация делает группы одинаковыми по всем признакам — наблюдаемым и ненаблюдаемым — до применения treatment. Единственное, что систематически различается — сам treatment.
Если после treatment среднее метрики в группах различается, мы можем утверждать: это различие вызвано treatment. Это каузальное утверждение, а не статистическое.
Для каждого пользователя i существуют два потенциальных исхода:
Проблема: мы никогда не наблюдаем оба исхода для одного пользователя. Это fundamental problem of causal inference.
| Пользователь | Y(0) | Y(1) | τi |
|---|---|---|---|
| A | 100 ₽ | 120 ₽ | +20 ₽ |
| B | 50 ₽ | 45 ₽ | −5 ₽ |
| C | 200 ₽ | 230 ₽ | +30 ₽ |
| D | 0 ₽ | 0 ₽ | 0 ₽ |
Мы не можем вычислить ATE напрямую (мы видим только одну колонку на пользователя), но рандомизация позволяет оценить ATE через разность средних между группами.
ATE — это среднее по всем пользователям. Оно не говорит, что эффект одинаков для всех. Пользователь A получил +20 ₽, пользователь B потерял 5 ₽ — но в среднем treatment полезен.
Когда пользователь попал в тест-группу, мы видим Yi(1). Что было бы без treatment (Yi(0)) — мы не знаем. Это не проблема данных, а фундаментальное ограничение: один человек не может одновременно получить и не получить treatment.
Рандомизация обходит это: контрольная группа — статистический заменитель контрфактуального состояния тестовой группы. Они неидентичны поюзерно, но одинаковы в среднем.
При корректной рандомизации ATE = ATT. Но при selection bias (нерандомизированная выборка, conditional-метрика) они расходятся.
Определение: каждый пользователь с равной вероятностью попадает в тест или контроль, независимо от своих характеристик.
Продуктовый пример: split на уровне user_id через хеш-функцию. hash(user_id, salt) % 100 < 50 → тест.
Что ломается при нарушении: если в тест попадают более активные пользователи — разница между группами отражает не treatment, а исходную неоднородность. Вы измеряете selection bias, а не каузальный эффект.
Определение: потенциальный исход пользователя i зависит только от его собственного treatment-статуса, а не от treatment-статуса других пользователей.
Продуктовый пример (нарушение): маркетплейс. Продавец в тест-группе получает новый алгоритм ранжирования → его товары показываются чаще → продавцы в контроле теряют показы. Эффект одного пользователя «переливается» в результат другого.
Что ломается при нарушении: ATE смещён. Если treatment одних улучшает метрику за счёт других, наивная оценка завышает реальный эффект. В пределе — zero-sum: суммарного эффекта нет, но A/B-тест показывает значимость.
Определение: наблюдаемый исход равен потенциальному исходу для назначенного treatment. Yobs = Y(1) если treatment = 1, Yobs = Y(0) если treatment = 0.
Продуктовый пример (нарушение): эксперимент включает новую фичу, но из-за бага 15% пользователей тест-группы видят старую версию. Наблюдаемый Y для этих пользователей — не Y(1) и не Y(0), а что-то среднее.
Что ломается при нарушении: эффект размывается (attenuation bias). ITT-оценка (Intent-to-Treat) занижает реальный эффект, потому что часть тестовой группы фактически не получила treatment.
Единица рандомизации — на каком уровне мы назначаем treatment. Единица анализа — на каком уровне мы измеряем метрику. Если они не совпадают, возникают проблемы с корреляцией и интерпретацией.
Стандарт: рандомизация по user_id. Один пользователь = одно наблюдение в анализе. Метрики: CR, число сессий, revenue per user — всё агрегируется до пользователя.
AOV = GMV / заказы. Рандомизация по пользователям, но метрика — на уровне заказа. У одного пользователя может быть 1 заказ или 50. Наблюдения (заказы) от одного пользователя скоррелированы → наивный t-test на заказах занижает дисперсию.
Решение: агрегировать до пользователя (delta-method для ratio) или учитывать кластерную структуру (cluster-robust SE с кластером = user).
CTR = клики / показы. Рандомизация по пользователям, но метрика — на уровне показа. Один пользователь генерирует 10–1000 показов. Показы одного пользователя не независимы.
Дополнительная опасность: treatment может влиять на число показов (treatment-affected exposure). Если алгоритм меняет частоту показов, CTR = clicks/impressions может снижаться даже при росте кликов — эффект разбавления.
Решение: (1) Агрегировать до per-user CTR. (2) Анализировать clicks и impressions как отдельные метрики. (3) Проверить стабильность числа показов между группами.
Когда SUTVA нарушена на уровне пользователя — эффект «переливается» между пользователями. Типичные ситуации:
ICC (Intra-Cluster Correlation) — доля общей дисперсии, объяснённая принадлежностью к кластеру.
Если ICC = 0.05 и средний кластер = 1000 пользователей, design effect ≈ 51. Это значит, что вам нужно в 51 раз больше пользователей, чем при user-level рандомизации, для той же мощности.
Гео-эксперимент с 20 городами и 2M пользователей имеет эффективный N ≈ 20, а не 2M. Если аналитик использует N = 2M в power analysis, он получает power = 99%. Реальная power — 15–20%. Эффект не воспроизводится.
Пользователь из контрольной группы видит результаты treatment через другой канал. Пример: эксперимент с новой ценой. Пользователь контроля видит скриншот новой цены в чате друга → меняет поведение. Контроль «загрязнён» — ATE занижен.
Двусторонний маркетплейс: treatment для покупателей влияет на продавцов, и наоборот. Социальная сеть: treatment для одного пользователя влияет на контент, который видят его друзья.
Следствие: ATE включает прямой эффект + spillover. Наивная оценка может как завышать (если spillover положительный), так и занижать (если zero-sum).
Анализ результатов только среди пользователей, совершивших действие после начала эксперимента. Пример: «средний чек среди покупателей» — ARPPU. Если treatment увеличил конверсию, состав «покупателей» в тесте и контроле различается. Вы сравниваете разные популяции.
Правило: не conditionируйте на post-treatment переменные. Используйте ITT-метрики или двухэтапные процедуры.
Менее очевидный случай. Пример: анализ «конверсия среди активных пользователей», где «активность» зависит и от treatment, и от конверсии. Conditionирование на collider создаёт ложную ассоциацию.
Правило: перед анализом проверьте — зависит ли ваша подвыборка от treatment? Если да — это conditioning на post-treatment переменную.
A/B-тест — единственный надёжный способ установить каузальную связь в продукте. Но только при соблюдении трёх условий: рандомизация, отсутствие интерференции, консистентность.
Нарушение любого из них не просто снижает точность — оно делает оценку смещённой. Вы принимаете решение на основе числа, которое систематически отличается от реального эффекта. И никакое увеличение выборки это не исправит.
Прежде чем выбирать статкритерий (Модуль 04) — убедитесь, что эксперимент каузален. Это не формальность. Это фундамент.