Serving & Production
~30 мин

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 тестов

1) Peeking — смотреть результаты раньше времени и останавливать тест при «значимости». Решение: фиксируй длительность заранее или используй sequential testing. 2) Multiple comparisons — тестируешь 10 метрик, одна «значима» случайно (p=0.05 → 1 из 20 ложноположительных). Решение: Bonferroni correction. 3) Network effects — пользователи влияют друг на друга (соцсети). Решение: кластерная рандомизация.

💡 Как это в реальной работе

Новая модель готова → shadow mode на 2-3 дня (проверяем, что не падает и предсказания адекватные) → canary 5% трафика на неделю → смотрим бизнес-метрики (CTR, revenue) → если ОК, раскатываем на 100%. Весь процесс занимает 2-3 недели. Если метрики хуже — откатываемся, разбираемся.

🎯 На собесе

Как организовать A/B тест ML-модели? 1) Shadow mode для safety check. 2) Canary: 5% → 50% → 100%. 3) Сплит по хешу user_id (consistency). 4) Метрики: бизнесовые (CTR, revenue) > ML-метрики. 5) Минимум 1-2 недели, power analysis для размера выборки. 6) Interleaving для рекомендаций.