A/B тестирование ML
Shadow mode, canary deploys, interleaving, статзначимость для ML-экспериментов.
A/B тестирование ML — проверяем модель на живом трафике
Офлайн-метрики говорят: новая модель лучше на 2% AUC. Но офлайн ≠ онлайн. Может быть: модель быстрее отвечает «нет» (хорошо для latency, плохо для revenue). Или модель лучше на исторических данных, но хуже на новых паттернах. A/B тест — единственный способ проверить влияние на бизнес-метрики.
Сплитование трафика
Ключевое правило: один пользователь всегда видит одну и ту же модель (consistency). Если пользователь видит то старую, то новую модель — результаты невалидны. Стандартный подход — детерминированный хеш от user_id + experiment_name: bucket = hash(user_id:experiment) % 100. Если bucket < treatment_pct — новая модель, иначе старая. Один и тот же пользователь всегда попадает в одну группу.
import hashlib
def get_group(user_id: str, experiment: str, treatment_pct: int = 10) -> str:
"""Детерминированный сплит: один юзер = одна группа (всегда)."""
bucket = int(hashlib.md5(f"{user_id}:{experiment}".encode()).hexdigest(), 16) % 100
return "treatment" if bucket < treatment_pct else "control"
group = get_group("user-123", "churn_v3", treatment_pct=10)
prediction = new_model.predict(features) if group == "treatment" else old_model.predict(features)
log_prediction(user_id, group, prediction, experiment="churn_v3")Стратегии деплоя новых моделей
- Shadow mode — новая модель работает параллельно, но пользователь видит старую. Логируем предсказания обеих. Сравниваем без риска
- Canary deployment — 1-5% трафика на новую модель. Если метрики ОК → 10% → 50% → 100%. Минимальный риск
- Blue/Green — две полные копии: Blue (текущая), Green (новая). Переключаем трафик мгновенно. Быстрый откат
- Interleaving — обе модели генерируют результаты, пользователь видит смешанный список. Мощнее A/B для рекомендаций — считаем клики по каждой модели
Shadow mode реализуется просто: production-модель отвечает пользователю, shadow-модель работает параллельно и логирует предсказания (пользователь их НЕ видит). Через 2-3 дня сравниваешь результаты. Если shadow не падает и предсказания адекватные — переходишь к canary. Interleaving используется для рекомендаций: обе модели генерируют ранжирование, пользователь видит чередующийся список (Team Draft алгоритм), а мы считаем, чьи рекомендации получили больше кликов.
Статзначимость — когда останавливать тест
Welch t-test (не требует равных дисперсий) сравнивает средние метрик двух групп и даёт p-value. Если p < 0.05 — разница статистически значима. Но кроме p-value важны: Cohen's d (размер эффекта), 95% confidence interval для разницы, relative uplift в процентах. Перед запуском теста сделай power analysis — рассчитай минимальный размер выборки для ожидаемого эффекта (effect_size=0.05, power=0.8, alpha=0.05).
from scipy import stats
from statsmodels.stats.power import TTestIndPower
import numpy as np
# Welch's t-test
t_stat, p_value = stats.ttest_ind(
treatment_metric, control_metric, equal_var=False
)
diff = treatment_metric.mean() - control_metric.mean()
relative_uplift = diff / control_metric.mean() * 100
print(f"p={p_value:.4f}, uplift={relative_uplift:.2f}%")
# Power analysis — сколько пользователей нужно
sample_size = TTestIndPower().solve_power(
effect_size=0.05, power=0.8, alpha=0.05, ratio=1.0
)
print(f"Нужно {int(sample_size)} юзеров в каждой группе")⚠️ Типичные ошибки A/B тестов
💡 Как это в реальной работе
🎯 На собесе
Материалы
Практика A/B тестирования ML в Avito.
Interleaving для рекомендательных систем от Netflix.
Введение в A/B тестирование для ML.
Классическая работа о подводных камнях A/B тестов.