Головна▸Статті▸MLOps та продакшн

A/B тестування для ML моделей

Тестування ML моделей у продакшні - дизайн експериментів, вибір метрик, обробка інтерференції та статистична значущість для ML A/B тестів.

mysimulator teamОновлено 2026-01≈ 6 хв читання▶ Open the simulation

A/B тестування - це спосіб валідувати, що нова ML модель дійсно покращує бізнес-результати. Offline метрики необхідні, але недостатні - моделі, що виграють offline, часто програють online. Продакшн-експерименти необхідні для впевнених рішень про деплой.

Де це використовується

A/B тестування для ML критичне у всіх ML застосуваннях:

Компанії з розвиненим ML: Netflix, Spotify, Google, Meta, Amazon постійно проводять тисячі експериментів.

Типові дані

Аспект Типові значення
Користувачів на експеримент 10K-10M
Тривалість експерименту 1-4 тижні
Кількість варіантів 2-5
Чутливість метрики 0.5%-5% MDE
Експериментів одночасно 10-1000

Джерела даних: - Логи призначення користувачів - Event streams (кліки, конверсії, дохід) - Сесійні та user фічі - Передбачення моделей та версії

Що ви робите на практиці

  1. Визначте гіпотезу - Яке покращення очікуєте і чому?
  2. Оберіть метрики - Primary, secondary та guardrail метрики
  3. Дизайн експерименту - Unit, тривалість, sample size, allocation
  4. Реалізуйте безпечно - Ramping, kill switches, моніторинг
  5. Запустіть експеримент - Збирайте дані, моніторте здоров'я
  6. Аналізуйте результати - Статистична значущість, сегментний аналіз
  7. Приймайте рішення - Ship, ітерація, або kill
  8. Документуйте уроки - Що спрацювало, що ні, чому

Спочатку бейзлайн

Перед тестуванням нової моделі переконайтесь, що маєте:

# Вимоги до бейзлайну
baseline_metrics = {
    'primary': 'conversion_rate',
    'secondary': ['revenue_per_user', 'session_duration'],
    'guardrails': ['latency_p99', 'error_rate', 'user_complaints']
}

# Історична варіація для розрахунку sample size
historical_std = calculate_metric_std(baseline_metrics['primary'])
baseline_mean = calculate_metric_mean(baseline_metrics['primary'])

Чому бейзлайн важливий: - Варіація визначає необхідний sample size - Встановлює що є "нормальним" - Ідентифікує сезонність та тренди - Визначає пороги guardrails

Дизайн експерименту

Ключові рішення:

Рішення Опції Міркування
Unit рандомізації Користувач, сесія, запит Консистентність vs sample size
Traffic split 50/50, 90/10, поетапний Ризик vs швидкість
Тривалість Дні до тижнів Сезонність, sample size
Triggering Всі користувачі, тільки eligible Dilution vs power

Розрахунок sample size:

from scipy import stats
import numpy as np

def sample_size_per_variant(
    baseline_rate: float,
    mde: float,  # Minimum detectable effect (відносний)
    alpha: float = 0.05,
    power: float = 0.80
) -> int:
    """Розрахунок sample size для two-proportion тесту."""
    p1 = baseline_rate
    p2 = baseline_rate * (1 + mde)

    effect_size = abs(p2 - p1) / np.sqrt((p1*(1-p1) + p2*(1-p2)) / 2)

    z_alpha = stats.norm.ppf(1 - alpha/2)
    z_beta = stats.norm.ppf(power)

    n = 2 * ((z_alpha + z_beta) / effect_size) ** 2
    return int(np.ceil(n))

# Приклад: 2% базовий CTR, хочемо детектувати 5% відносний lift
n = sample_size_per_variant(0.02, 0.05)  # ~63,000 на варіант

Вибір метрик

Категорії метрик:

Тип Призначення Приклади
Primary Головна метрика рішення Conversion rate, дохід
Secondary Додаткові інсайти Engagement, retention
Guardrail Захист від шкоди Latency, error rate, скарги
Debug Діагностика проблем Model confidence, coverage

Хороші метрики для ML експериментів: - Downstream бізнес-результати (не тільки accuracy моделі) - Достатньо чутливі для детекції очікуваного ефекту - Достатньо стабільні для розумних sample sizes - Спостережувані протягом експерименту

Поширені помилки: - Використання метрик моделі (AUC) замість бізнес-метрик - Забагато primary метрик (проблема множинного тестування) - Ігнорування довготривалих ефектів - Відсутність guardrails

Аналіз та статистика

Стандартний аналіз:

from scipy import stats

def analyze_experiment(control, treatment):
    """Two-proportion z-test для conversion rate."""
    n1, conversions1 = len(control), sum(control)
    n2, conversions2 = len(treatment), sum(treatment)

    p1 = conversions1 / n1
    p2 = conversions2 / n2

    p_pooled = (conversions1 + conversions2) / (n1 + n2)
    se = np.sqrt(p_pooled * (1 - p_pooled) * (1/n1 + 1/n2))

    z_stat = (p2 - p1) / se
    p_value = 2 * (1 - stats.norm.cdf(abs(z_stat)))

    return {
        'control_rate': p1,
        'treatment_rate': p2,
        'relative_lift': (p2 - p1) / p1,
        'p_value': p_value,
        'significant': p_value < 0.05
    }

Техніки зменшення варіації: - CUPED: Використання pre-experiment даних як коваріати - Стратифікація: Балансування по відомих confounders - Ratio метрики: Нормалізація по exposure

Корекція множинного тестування: - Bonferroni: α / кількість тестів - Holm-Bonferroni: Послідовне відхилення - FDR control: Benjamini-Hochberg

Режими відмов та чеклист налагодження

Перевірка SRM:

def check_srm(control_n, treatment_n, expected_ratio=0.5):
    """Перевірка sample ratio mismatch."""
    total = control_n + treatment_n
    expected_control = total * expected_ratio
    expected_treatment = total * (1 - expected_ratio)

    chi2 = ((control_n - expected_control)**2 / expected_control + 
            (treatment_n - expected_treatment)**2 / expected_treatment)

    p_value = 1 - stats.chi2.cdf(chi2, df=1)
    return p_value > 0.001  # Немає SRM якщо p > 0.001

ML-специфічні міркування

ML експерименти відрізняються від типових A/B тестів:

Аспект Стандартний A/B ML A/B
Treatment Статична зміна Динамічні передбачення
Ефекти Негайні Можуть потребувати часу
Інтерференція Зазвичай низька Може бути високою (рекомендації)
Дебагінг Простий Складний (поведінка моделі)

Обробка інтерференції: - Кластерна рандомізація: Рандомізація на рівні групи - Ego-cluster: Користувач + їх мережа - Switchback: Чергування treatment з часом - Holdout: Довготривалі holdout групи користувачів

ML-специфічні метрики для відстеження: - Зміни розподілу передбачень - Coverage (яка частка запитів використовує модель) - Вплив на latency - Здоров'я фіч

Чеклист для продакшну

Перед експериментом: - [ ] Гіпотеза задокументована - [ ] Метрики визначені та відстежуються - [ ] Sample size розраховано - [ ] Рандомізація верифікована (A/A тест) - [ ] Guardrails та alerting налаштовані - [ ] Kill switch готовий

Під час експерименту: - [ ] SRM перевірка щодня - [ ] Guardrails моніторяться - [ ] Не підглядати результати (окрім безпеки) - [ ] Документувати будь-які проблеми чи зміни

Після експерименту: - [ ] Повний аналіз завершено - [ ] Сегментний аналіз зроблено - [ ] Novelty effects перевірено - [ ] Рішення задокументовано - [ ] Уроки поширено

Інструменти та стек

Категорія Інструменти
Experimentation platforms Optimizely, LaunchDarkly, Eppo, Statsig
Кастомні платформи Внутрішні інструменти великих компаній
Аналіз Python (scipy, statsmodels), R
Логування Snowflake, BigQuery, event streams

Приклад міні-кейсу

Сценарій: E-commerce сайт тестує нову рекомендаційну модель, яка має збільшити purchase rate.

Налаштування: - Primary метрика: Purchase rate (бейзлайн: 3.2%) - Guardrails: Page latency p99 < 500ms, add-to-cart rate ≥ бейзлайну - MDE: 3% відносний lift - Sample size: 85K користувачів на варіант - Тривалість: 2 тижні

Виконання:

Тиждень 1:
- SRM перевірка: Пройдено (50.1% vs 49.9%)
- Guardrails: Всі зелені
- Попередньо: +4.2% purchase rate (p=0.08)

Тиждень 2:
- Фінальний аналіз: +3.8% purchase rate (p=0.02)
- Сегментний аналіз: Ефект сильніший для returning users (+5.1%)
- Novelty check: Ефект стабільний протягом тижнів

Результат: - Рішення: Ship нову модель - Вплив: +$2.4M річного доходу - Follow-up: Запустити holdout для довготривалих ефектів

Ключові уроки: - Чекали повну тривалість попри обнадійливі ранні результати - Сегментний аналіз виявив можливість для подальшої персоналізації - Вплив на latency був мінімальним (збільшення на 2ms)

Пов'язані сторінки

Додаткове читання

Спробуйте наживо

Дослідіть пов'язану модель на практиці: відкрийте A/B Test Optimizer — UCB1 Multi-Armed Bandit Live і змінюйте параметри під час роботи. Усе лишається у вашому браузері.

▶ Відкрити симуляцію A/B Test Optimizer — UCB1 Multi-Armed Bandit Live

Що ви знайшли?

Додати кроки відтворення (опційно)