Как должен вести себя MDE при запуске теста?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
MDE (Minimum Detectable Effect) при запуске теста
MDE (Минимальный детектируемый эффект) — это самое маленькое изменение метрики, которое ваш тест сможет надёжно обнаружить при заданных параметрах (размер выборки, продолжительность, уровень значимости). Это ключевой параметр для планирования A/B тестов, который определяет, стоит ли вообще запускать тест.
Что такое MDE простыми словами
Представьте себе:
- Текущая конверсия: 10%
- MDE: 2%
Это означает, что ваш тест с высокой вероятностью (обычно 80%) сможет обнаружить, если конверсия поднялась до 10% + 2% = 12%. Но если результат поднялся только на 1%, тест может его пропустить.
Как MDE ведёт себя при запуске теста
1. MDE ФИКСИРУЕТСЯ перед запуском теста
ВАЖНО: MDE должен быть рассчитан до запуска теста, а не вычислен после его завершения.
from statsmodels.stats.power import tt_ind_solve_power
# Параметры теста
alpha = 0.05 # уровень значимости (обычно 5%)
power = 0.80 # статистическая мощность (обычно 80%)
effect_size = 0.10 # MDE в виде Cohen's d
# Вычисляем требуемый размер выборки
n_per_group = tt_ind_solve_power(
effect_size=effect_size,
alpha=alpha,
power=power,
ratio=1.0 # одинаковые группы
)
print(f"Требуется {n_per_group:.0f} пользователей на группу")
2. MDE зависит от четырёх факторов
MDE зависит от:
├─ Уровня значимости α (обычно 5%)
├─ Статистической мощности (обычно 80%)
├─ Размера выборки (n пользователей на группу)
└─ Вариативности метрики (σ, стандартное отклонение)
Формула для MDE (для t-теста):
MDE = (z_α + z_β) * σ * √(2) / √(n)
Где:
z_α = 1.96 (для α = 0.05, two-tailed)
z_β = 0.84 (для power = 0.80)
σ = стандартное отклонение метрики
n = размер выборки на группу
3. Поведение MDE: инверсные зависимости
MDE УМЕНЬШАЕТСЯ, когда:
- ↑ Размер выборки (больше данных = более чувствительный тест)
- ↑ Длительность теста (больше времени = больше пользователей)
- ↑ Статистическая мощность (от 80% к 90%)
- ↓ Вариативность метрики (более стабильные данные)
MDE УВЕЛИЧИВАЕТСЯ, когда:
- ↓ Размер выборки
- ↓ Длительность теста
- ↓ Уровень мощности
- ↑ Вариативность метрики
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.stats.power import tt_ind_solve_power
# Как MDE зависит от размера выборки
sample_sizes = np.array([100, 500, 1000, 5000, 10000])
mdes = []
for n in sample_sizes:
# Обратный расчёт: какой effect_size при таком n?
effect = tt_ind_solve_power(
effect_size=None, # неизвестно
alpha=0.05,
power=0.80,
nobs1=n
)
mdes.append(effect)
print(f"n={n:5d} → MDE (Cohen's d) = {effect:.4f}")
# Видим закономерность: √n в знаменателе
print("\nВывод: MDE обратно пропорционален √n")
Практический пример расчёта MDE
Сценарий: Запуск теста улучшения кнопки в приложении
from statsmodels.stats.power import proportions_ztest
from statsmodels.stats.proportion import proportions_ztest, proportion_effectsize
# Текущие метрики
current_conversion = 0.12 # 12%
min_detectable_lift = 0.15 # хотим обнаружить +15% относительный лифт
target_conversion = current_conversion * (1 + min_detectable_lift) # 13.8%
# Параметры теста
alpha = 0.05 # 5% significance level (two-tailed)
power = 0.80 # 80% statistical power
alternative = 'two-sided'
# Рассчитываем эффект для пропорций
effect_size = proportion_effectsize(target_conversion, current_conversion)
print(f"Текущая конверсия: {current_conversion:.2%}")
print(f"Целевая конверсия: {target_conversion:.2%}")
print(f"Относительный лифт: {min_detectable_lift:.1%}")
print(f"Абсолютный MDE: {(target_conversion - current_conversion):.2%}")
print(f"Effect size (Cohen's h): {effect_size:.4f}")
# Требуемый размер выборки
from statsmodels.stats.power import tt_ind_solve_power
n_per_group = tt_ind_solve_power(
effect_size=effect_size,
alpha=alpha,
power=power,
ratio=1.0,
alternative='two-sided'
)
print(f"\nТребуемый размер выборки: {n_per_group:.0f} пользователей на группу")
print(f"Всего пользователей: {n_per_group * 2:.0f}")
print(f"Дневный трафик: 10000 пользователей")
print(f"Требуемая продолжительность теста: {(n_per_group * 2 / 10000):.1f} дней")
Как выбрать нужный MDE
Правило: MDE должен быть ПРАКТИЧЕСКИ ЗНАЧИМЫМ
Business Impact = Lift % × Traffic × Conversion Rate × ARPU
Если лифт даст бизнесу менее $10 000/месяц → не тестируй
Примеры разумных MDE:
| Метрика | MDE | Обоснование |
|---|---|---|
| Конверсия (12%) | 15% лифта (+1.8%) | Значимо для бизнеса |
| Retention (25%) | 10% лифта (+2.5%) | Влияет на LTV |
| CTR (2%) | 20% лифта (+0.4%) | Может быть слишком мал |
| Time-on-app (5 мин) | 10% лифта | Трудно обнаружить |
Поведение MDE во время теста: типичные ошибки
❌ ОШИБКА 1: Пересчитывать MDE во время теста
# НЕПРАВИЛЬНО!
while test_is_running:
current_data = fetch_data()
variance = calculate_variance(current_data)
mde = recalculate_mde(variance) # ❌ НЕЛЬЗЯ!
if current_effect > current_mde:
stop_test_early() # ❌ Это увеличит false positive rate!
❌ ОШИБКА 2: Остановить тест, если текущий эффект < MDE
НА ДЕНЬ 5: Effect = 1%, MDE = 2% → НЕДОСТАТОЧНО ДАННЫХ
→ ❌ Нельзя останавливать тест!
→ ✓ Нужно дождаться конца периода
✅ ПРАВИЛЬНОЕ ПОВЕДЕНИЕ MDE
def should_stop_test(days, daily_users, target_duration_days):
"""
MDE должен оставаться фиксированным.
Тест нужно запускать на определённый период.
"""
total_users = days * daily_users
# Логируем прогресс
if days % 7 == 0:
print(f"День {days}: собрано {total_users} пользователей")
print(f"Прогресс: {days}/{target_duration_days} дней")
# Останавливаем только в конце периода
if days >= target_duration_days:
return True # ✓ Пришло время анализировать результаты
return False
Итоговая таблица: MDE в зависимости от условий
| День теста | Собрано | Статус | Действие |
|---|---|---|---|
| День 2 | 100 | Слишком мало данных | Продолжить |
| День 7 | 700 | Эффект виден? | Продолжить |
| День 14 | 1400 | Приближаемся | Продолжить |
| День 28 | 2800 | ФИНАЛ → MDE достаточен | Анализировать |
Best Practices
1. Планирование теста:
# Шаг 1: Определить бизнес-метрику
desired_lift_pct = 15 # +15% от текущего
# Шаг 2: Рассчитать MDE
mde = calculate_mde(alpha=0.05, power=0.80, effect=desired_lift_pct)
# Шаг 3: Определить требуемый размер выборки
n_required = calculate_sample_size(mde)
# Шаг 4: Рассчитать продолжительность
test_duration_days = n_required / daily_traffic
# Шаг 5: ЗАФИКСИРОВАТЬ эти значения
log_test_design(mde, n_required, test_duration_days)
2. Во время теста:
- ✓ Ежедневно логируйте размер выборки
- ✓ НЕ смотрите на текущий p-value каждый день
- ✓ Следуйте плану
- ✗ Не заканчивайте рано, даже если результат очень хороший
- ✗ Не продлевайте тест бесконечно
3. После теста:
- Сравните финальный эффект с MDE
- Вычислите доверительный интервал
- Примите решение на основе эффекта И статистики