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

Как правильно спланировать A/B тест?

2.0 Middle🔥 241 комментариев
#Статистика и A/B тестирование

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Как правильно спланировать A/B тест

Основные этапы планирования

Планирование A/B теста — это критический процесс, который определяет корректность выводов. Правильное планирование включает определение гипотезы, расчёт размера выборки, выбор метрик и периода теста.

1. Формулировка гипотезы

Нулевая гипотеза (H0): вариант A и вариант B не различаются Альтернативная гипотеза (H1): вариант B лучше/отличается от варианта A

Примеры гипотез:

  • "Изменение цвета кнопки с синего на красный повысит CTR на 5%"
  • "Новый алгоритм рекомендаций увеличит engagement на 10% или более"

2. Выбор метрики (Metric Selection)

Выбери одну первичную метрику и несколько вторичных:

# Пример метрик для e-commerce
Primary: conversion_rate = purchases / sessions
Secondary: avg_order_value, retention_rate, customer_satisfaction

Важно:

  • Метрика должна быть измеримой и объективной
  • Используй метрики с малой волатильностью для надёжности
  • Избегай слишком сложных метрик на начальном этапе
  • Убедись, что метрика отражает реальный бизнес-результат

3. Определение минимально значимого эффекта (MDE)

MDE (Minimum Detectable Effect) — минимальный прирост, который мы считаем практически важным.

# Пример: текущая конверсия 2%, MDE = 10% (относительный прирост)
# Ожидаемая конверсия в варианте B = 2% * 1.1 = 2.2%

current_conversion = 0.02
mde_relative = 0.10  # 10% увеличение
expected_conversion = current_conversion * (1 + mde_relative)
print(f"Expected: {expected_conversion:.4f}")

Выбор MDE:

  • Слишком маленький MDE требует большой выборки и дорогой тест
  • Слишком большой MDE может пропустить реальные эффекты
  • Основывайся на бизнес-целях и текущих метриках

4. Расчёт размера выборки (Sample Size)

Используй формулу для расчёта требуемого размера выборки по группам:

import numpy as np
from scipy import stats

def calculate_sample_size(baseline_rate, mde, alpha=0.05, power=0.8):
    """
    Расчёт размера выборки для бинарной метрики.
    
    baseline_rate: текущий уровень конверсии (e.g., 0.02)
    mde: относительный минимальный эффект (e.g., 0.10)
    alpha: уровень значимости (type I error, обычно 0.05)
    power: статистическая мощность (1 - beta, обычно 0.8)
    """
    
    # Расчёт вероятностей
    p1 = baseline_rate
    p2 = baseline_rate * (1 + mde)
    
    # Стандартные отклонения
    s1 = np.sqrt(p1 * (1 - p1))
    s2 = np.sqrt(p2 * (1 - p2))
    pooled_std = np.sqrt((s1**2 + s2**2) / 2)
    
    # Z-значения
    z_alpha = stats.norm.ppf(1 - alpha / 2)  # двусторонний тест
    z_beta = stats.norm.ppf(power)
    
    # Размер выборки на группу
    n_per_group = (z_alpha + z_beta)**2 * (2 * pooled_std**2) / (p2 - p1)**2
    
    return n_per_group

# Пример
baseline = 0.02  # 2% конверсия
mde = 0.10       # 10% относительный прирост
n = calculate_sample_size(baseline, mde)
print(f"Размер выборки на группу: {n:,.0f}")
print(f"Всего: {n * 2:,.0f} наблюдений")
print(f"При 10k трафика в день: {n * 2 / 10000:.1f} дней")

5. Выбор периода теста и интервала конфиденции

Минимальная продолжительность:

  • Не менее 1 полного недельного цикла (чтобы учесть суточные колебания)
  • Лучше 2-4 недели для стабильности
  • Минимум 1000-5000 наблюдений на группу

Нельзя:

  • Заканчивать тест раньше запланированного времени, если видно статистическую значимость (peeking problem)
  • Изменять гипотезу после начала теста (HARKing — Hypothesizing After Results are Known)

6. Рандомизация и контроль

# Правильная рандомизация: по user_id
import hashlib

def get_variant(user_id, test_name, split=0.5):
    """
    Детерминированная рандомизация: один пользователь всегда в одной группе.
    """
    hash_value = int(hashlib.md5(f"{user_id}_{test_name}".encode()).hexdigest(), 16)
    return "A" if hash_value % 100 < split * 100 else "B"

# Проверка баланса
test_users = range(10000)
variants = [get_variant(user_id, "button_color") for user_id in test_users]
print(f"A: {variants.count(A)}, B: {variants.count(B)}")

7. Статистический анализ результатов

from scipy.stats import chi2_contingency

def analyze_ab_test(conversions_a, total_a, conversions_b, total_b, alpha=0.05):
    """
    Chi-square тест для сравнения двух пропорций.
    """
    contingency_table = [
        [conversions_a, total_a - conversions_a],
        [conversions_b, total_b - conversions_b]
    ]
    
    chi2, p_value, dof, expected = chi2_contingency(contingency_table)
    
    rate_a = conversions_a / total_a
    rate_b = conversions_b / total_b
    lift = (rate_b - rate_a) / rate_a * 100
    
    is_significant = p_value < alpha
    
    print(f"Конверсия A: {rate_a:.4f} ({conversions_a}/{total_a})")
    print(f"Конверсия B: {rate_b:.4f} ({conversions_b}/{total_b})")
    print(f"Lift: {lift:.2f}%")
    print(f"P-value: {p_value:.4f}")
    print(f"Статистически значимо (alpha={alpha}): {is_significant}")
    
    return is_significant, lift, p_value

# Пример
analyze_ab_test(conversions_a=200, total_a=10000,
                conversions_b=240, total_b=10000)

8. Контроль побочных эффектов

  • Multy-testing correction: если проверяешь много гипотез, используй Bonferroni коррекцию
  • Симпсон парадокс: проверяй результаты по сегментам
  • Утечка эффекта: если пользователи видят оба варианта, это нарушает тест
  • Сезонность: учитывай дни недели, праздники, маркетинг-события

Чеклист планирования A/B теста:

  1. Сформулирована чёткая гипотеза
  2. Выбрана первичная метрика
  3. Определён MDE
  4. Рассчитан размер выборки
  5. Спланирован период теста (минимум 2 недели)
  6. Описана процедура рандомизации
  7. Определены критерии остановки
  8. Проверена мощность теста
  9. Согласован план анализа заранее
  10. Задокументировано, кто принимает решение по результатам

Правильное планирование гарантирует, что результаты теста будут надёжными и позволят принять правильное бизнес-решение.