← Назад к вопросам

Как должен вести себя MDE при запуске теста?

3.0 Senior🔥 151 комментариев
#A/B тестирование#Статистика и математика

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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 в зависимости от условий

День тестаСобраноСтатусДействие
День 2100Слишком мало данныхПродолжить
День 7700Эффект виден?Продолжить
День 141400ПриближаемсяПродолжить
День 282800ФИНАЛ → 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
  • Вычислите доверительный интервал
  • Примите решение на основе эффекта И статистики