Интерпретация результатов A/B-теста
Significance ≠ важность. Сегменты осторожно, ловушки: peeking, novelty, confounders.
Интерпретируй результаты A/B-теста.
Primary: {{primary_metric}} Контекст: {{test_context}}
Главное: 4 вопроса, не 1
Плохой ответ: «p < 0.05, выкатываем». Хороший — пройди все 4:
- Significant ли результат статистически? (p-value)
- Важен ли он практически? (effect size vs MDE)
- Не упали ли guardrails?
- Не нарушены ли допущения? (peeking, sample, segments)
1. Statistical significance
| Что смотреть | Норма |
|---|---|
| p-value | < 0.05 для основной гипотезы |
| Confidence interval | целиком в нужную сторону, не пересекает 0 |
| Effect size | > MDE, заявленного до теста |
Ловушка confidence interval: «+2% ± 8%» — это [−6%, +10%]. Значит, реальный эффект может быть −6%. «Significant» не значит «уверены в +2%».
2. Practical importance
Significance ≠ важность. Пример: тест на 5M юзеров, lift = +0.3%, p = 0.001.
Significant? Да
Important? Зависит:
- 0.3% × $50M revenue = $150k/год — да, важно
- 0.3% × DAU при cost запуска = engineering month — может, нет
Правило: до теста запиши MDE. Если lift < MDE — даже при p < 0.001 ты заявил, что это «не важно». Не отказывайся от обещания.
3. Guardrails
| Гvardrail метрика | Что проверить |
|---|---|
| Conversion rate | Не упала ли вторичная конверсия |
| Latency / errors | Не сломали ли страницу |
| Refunds / churn | Подняли ли долгосрочную потерю |
| Support tickets | Не выросли ли жалобы |
Любой guardrail упал значимо → не катить, даже если primary вырос. Это не теорема, это договор до запуска.
4. Segment analysis — осторожно
Сильный соблазн: «в целом не сработало, но на iPhone +10%». Это часто multiple testing artifact.
| Правильно | Неправильно |
|---|---|
| Сегменты заранее задекларированы | Перебираешь сегменты post-hoc, пока не найдёшь «победителя» |
| Применил поправку (Bonferroni / Holm) | Каждый сегмент с α = 0.05 |
| Подтвердил на отдельной выборке (replication) | Один раз увидел — катишь только на сегмент |
| 3-5 сегментов максимум | 20 сегментов, один значимый |
Правило большого пальца: если перебираешь 20 сегментов с α = 0.05, в среднем 1 будет «значимым» по чистой случайности.
Когда сегментное решение оправдано:
- Прединфо: знаешь, что use case различен по сегменту
- Один и тот же эффект устойчиво воспроизводится в нескольких циклах
- Бизнес-объяснение, а не «нашли в данных»
5. Ловушки
Peeking
Если смотришь каждый день и катишь как только p < 0.05 — реальный α у тебя ~ 0.3, не 0.05. Treat: sequential testing (Always Valid Inference / mSPRT) или фикcируй заранее даты read.
Novelty effect
Юзеры реагируют на «новое» в первую неделю, потом эффект тает. Симптомы:
- Резкий взлёт первые дни → плато → падение к baseline на 4-6 неделе
- Repeat users показывают меньший эффект чем new users
Treat: смотри cohort по неделям, а не aggregate. Дай тесту дотянуть minimum 2-3 weeks даже при ранней «победе».
Confounders
| Конфаундер | Симптом |
|---|---|
| Релиз другой фичи параллельно | Effect не объясняется только твоим изменением |
| Сезонность (праздник, школа) | Baseline дрейфует в обеих ветках |
| Маркетинг кампания | Трафик сменил состав |
| Bug в треккинге | Один из вариантов недоучитывает события |
Чек до релиза: трэкинг работает в обеих ветках одинаково? — SRM-тест: ratio assigned should = 50/50 within tolerance.
Survivorship bias
Считаешь retention только по тем, кто остался. Если treatment отпугнул слабых юзеров — оставшиеся «лучше», но total revenue упал.
Treat: смотри intent-to-treat (включая ушедших), не per-protocol.
Simpson's paradox
Treatment проигрывает в каждом сегменте, но выигрывает в aggregate — потому что состав сегментов изменился. Проверь, что доли сегментов одинаковы в treatment и control.
6. Шаблон решения
| Критерий | Результат | OK? |
|---|---|---|
| Primary lift | +3.2% (CI [+1.1%, +5.3%]) | Да (CI > 0) |
| vs MDE (предзаявлен 2%) | Да | Да |
| Primary p-value | 0.003 | Да |
| Guardrail: conversion | −0.4% (CI [−1.1%, +0.3%]) | Да (не значимо) |
| Guardrail: support tickets | +12% (p = 0.01) | НЕТ |
| Длительность | 21 день | Да |
| SRM check | 50.2% / 49.8% (p > 0.5) | Да |
| Peeking | Финальный read только | Да |
Решение: НЕ катить. Сначала разобраться с +12% support tickets.
Что НЕ делать
❌ Решать по одной цифре (p < 0.05) — нужен полный чек-лист ❌ Перебирать сегменты пока не найдёшь «победителя» — multiple testing ❌ Продлевать тест когда p = 0.07 — peeking ❌ Игнорировать guardrail «потому что primary вырос» — нарушение договора ❌ Останавливать рано из-за «явной победы» — novelty bias ❌ Не делать SRM check — самый частый источник ложных результатов ❌ Делать выводы по сегменту с n < минимум_для_сегмента
На выходе
- Заполненная таблица: primary / guardrails / sanity checks
- Ясное решение: ship / kill / replicate / debug
- Если ship — что мониторить первые 4 недели после
- Если kill — что узнали (не «провал», а «знание»)
- Если replicate — дизайн повторного запуска (другой сегмент / время)
Декомпозиция фичи в user stories
Разбить фичу на маленькие истории формата «As a … I want … so that …» с acceptance criteria.
Blind A/B eval двух промтов
Сравнить prompt v1 vs v2 на одних inputs: judge (Claude или человек), статистическая значимость, защита от cherry-picking.
Архитектура feature flags
Типы флагов (release/experiment/ops/permission), хранение, оценка, тех-долг и удаление.