Условие
Что такое A/A-тест? Зачем его запускают перед A/B-тестом и какие проблемы он помогает обнаружить?
Решение
Определение
A/A-тест — это эксперимент, в котором обе группы получают одинаковое воздействие (или его отсутствие). Ожидаемый эффект нулевой, но есть случайные колебания метрик из-за варианса выборки.
Что проверяет
-
Корректность сплитования (Sample Ratio Mismatch). Если делите 50/50, после фильтрации группы должны быть ≈ равны. Сильное расхождение (например, 49% vs 51% при N=200k) — сигнал бага в randomizer’е или в фильтре.
from scipy.stats import chisquare stat, p = chisquare([n_a, n_b], f_exp=[(n_a+n_b)/2]*2) if p < 0.001: raise ValueError("SRM detected") -
Корректность логирования. Если в группе A считается на 5% меньше событий, чем в B — баг трекинга, а не эффект.
-
Ложноположительные срабатывания. Если метрика «реагирует» на отсутствие изменений (p<0.05 в нескольких из десятка A/A) — критерий поломан или метрика имеет аномальное распределение.
-
Реалистичная оценка вариативности. Распределение разностей в A/A — это эмпирическое распределение шума. Полезно для:
- Калибровки CUPED,
- Эмпирического определения порога значимости («10% A/A с p<0.05 → подумайте о фильтрации»).
Когда запускать
- Перед первым релизом новой системы A/B-тестирования;
- После рефакторинга randomizer / event tracker;
- Если предыдущий A/B дал неожиданно «значимый» эффект на здравомысленно-нейтральной фиче;
- В «перманентном A/A» режиме (постоянная контрольная группа vs контрольная) для мониторинга платформы.
Пример sanity check
import scipy.stats as st
# A/A: ожидаем, что доля значимых ≈ α = 5%
results = [run_aa_test() for _ in range(1000)]
share_significant = sum(p < 0.05 for p in results) / len(results)
print(share_significant) # должно быть ~0.05Если получили 12% — критерий ломается. Если 1% — слишком консервативен.
Подводные камни
- Один A/A-тест не репрезентативен. Нужно набор A/A (10–50) для оценки α-калибровки.
- Sample Ratio Mismatch ловится только статистикой. Эмпирический «глаз» не различит 49.5% vs 50% на больших данных.
- «A/A прошёл — A/B можно». A/A проверяет инфраструктуру, не магически валидирует A/B.
- A/A с post-randomization фильтрами. Если фильтр зависит от поведения (например, «активные пользователи»), он может породить SRM даже на «чистом» сплите.
- A/A на маленьком N. Шум сильный — не делайте выводов «всё ок» при N<10k.
Эталонный ответ
A/A-тест проверяет инфраструктуру: SRM, корректность логирования, калибровку критерия (доля значимых должна быть ≈ α). Запускают перед запуском новой A/B-платформы, после изменений в трекинге и при подозрительных результатах. Один A/A не показателен — нужен набор.