RecSys · учебник
Тренажёр Виджеты Повторение О проекте Все главы ← Метрики Классика →

Часть I · Постановка и измерение · глава 4 из 19

Валидация и эксперимент

Метрику посчитать легко, поверить ей трудно. Случайный сплит завышает качество через признаки, которых вы не подозревали; офлайн и онлайн расходятся систематически; A/B требует больше трафика, чем кажется, а привычка заглядывать в результаты превращает пять процентов ложных срабатываний в двадцать один. Всё это считается заранее — и здесь посчитано.

Что унести из главы
  • Сплит только временной. При случайном таргет протекает через любой признак, проксирующий популярность: счётчик уже содержит будущие клики.
  • Бейзлайн популярности обязателен. Не как соперник, а как измерительный прибор: он показывает, сколько метрики даётся вообще без персонализации.
  • Вдвое меньший эффект — вчетверо больше данных. Проверено численно: отношение 3.98. Поэтому «давайте померим +0.1%» обычно означает «нам не хватит трафика».
  • Подглядывание ломает уровень значимости. Одна проверка в конце — честные 5.0%, ежедневная за две недели — 21.5% ложных срабатываний на A/A-тесте.

1. Сплит

Почему единственный честный сплит — временной

Аргумент простой и работает всегда. В любом реальном датасете есть признаки, так или иначе проксирующие популярность: счётчик показов, число покупок, средний рейтинг, «сколько раз добавили в избранное».

Что именно течёт

При случайном сплите часть взаимодействий одного и того же айтема попадает в трейн, часть — в тест. Но признак «число покупок» посчитан по всем данным, включая тестовые. Значит, он уже содержит информацию о том, что произойдёт в тесте.

Модель этим пользуется — и совершенно правомерно с точки зрения оптимизации: признак информативен. Просто в проде такого признака не существует, потому что будущее ещё не наступило.

Утечка тем коварнее, что не выглядит утечкой: вы не подмешивали таргет в признаки руками, вы просто посчитали агрегат по всему датасету. И заметить это по метрикам нельзя — они как раз выглядят прекрасно.

Правильно: выбрать глобальную отсечку по времени \(T\), обучаться на всём до неё, проверяться на всём после. Все агрегаты и счётчики тоже считаются только по данным до \(T\) — это отдельная дисциплина, о которой легко забыть.

случайный сплит: тест перемешан с трейном во времени Счётчик популярности, посчитанный по всему, уже знает про красные интервалы. временной сплит: одна отсечка, и всё до неё обучение проверка T
Агрегаты и счётчики тоже считаются только слева от отсечки — иначе временной сплит перестаёт быть временным.
Отдельно про leave-one-out

Схема «убрать у каждого пользователя последнее взаимодействие в тест» популярна в академических статьях и выглядит временной. Но отсечка у каждого пользователя своя, а значит для одного пользователя тестовый момент лежит в прошлом другого — и агрегаты снова текут.

Это одна из известных методологических проблем сравнения рекомендательных моделей в литературе: часть опубликованных приростов не воспроизводится именно из-за протокола, а не из-за моделей.

Решение про холодных надо принять явно

После временного сплита в тесте неизбежно окажутся пользователи и айтемы, которых не было в обучении. Что с ними делать — решение, а не деталь реализации, и от него сильно зависит число.

ВариантЧто измеряетЧем плох
выбросить холодных из тестакачество на знакомой аудиториизавышает: в проде холодные есть всегда, и их доля растёт
оставить и считать промахомчестное сквозное качествосмешивает две разные проблемы — качество модели и покрытие холодного старта
считать отдельно две метрикиобе величины по отдельностидороже, но это единственный вариант, по которому можно принимать решения

Третий вариант и рекомендуется: одна метрика на тёплых, вторая на холодных, и доля холодных как отдельное число. Иначе улучшение модели и ухудшение покрытия смешиваются в одно движение.

2. Бейзлайн, без которого нельзя

Прежде чем сравнивать модели между собой, нужно сравнить их с отсутствием модели. Бейзлайн — топ популярного за окно.

Это измерительный прибор, а не соперник

Бейзлайн популярности отвечает на вопрос, сколько метрики набирается вообще без персонализации. Ответ обычно неприятно высокий — и именно поэтому его надо знать.

  • Если ваша модель обходит популярность на проценты, вопрос «а стоит ли она своей сложности» становится содержательным.
  • Если не обходит вовсе — почти наверняка ошибка в протоколе, а не в модели.
  • Если обходит подозрительно сильно — ищите утечку. Слишком хороший результат на первом прогоне это симптом, а не успех.

И тот же приём применяется к любой новой стадии: прежде чем добавлять источник кандидатов, посмотрите, что даёт «взять больше из существующего».

3. Почему офлайн и онлайн расходятся

Разрыв между офлайн-метрикой и результатом A/B — не аномалия, а норма, и причины у него системные.

ПричинаМеханизм
Офлайн меряется на чужой политикеотложенная выборка собрана прошлой системой. Новая модель предлагает другое, и как на это отреагируют, в логах не написано
Метрика — проксиNDCG растёт, удержание не двигается: они связаны, но не одно и то же
Позиционное смещение в разметкеофлайн модель хвалят за воспроизведение прошлого порядка, включая его смещения
Продуктовые эффекты вне моделискорость ответа, вёрстка, доля рекламы — в офлайне их нет вовсе
Новизна и привыканиевсплеск в первые дни на новизне и откат потом; офлайн не видит времени

Практический вывод не «офлайн бесполезен», а «офлайн — фильтр». Он дёшево отсеивает заведомо плохое; решение принимает эксперимент. Держать между ними связь помогает простая привычка: записывать офлайн-прогноз до запуска и потом сверять. Через десяток экспериментов вы узнаете переводной коэффициент своей системы, и это ценнее любой отдельной метрики.

4. Сколько нужно трафика

Главная арифметика перед экспериментом: хватит ли данных, чтобы вообще различить эффект, который вы надеетесь получить.

Размер выборки на группу

Для доли (конверсия, CTR) при уровне значимости 5% и мощности 80%:

$$ n \;=\; \frac{\Bigl(z_{\alpha/2}\sqrt{2\bar p(1-\bar p)} \;+\; z_{\beta}\sqrt{p_0(1-p_0) + p_1(1-p_1)}\Bigr)^2}{(p_1 - p_0)^2} $$

где \(p_0\) — базовая конверсия, \(p_1\) — ожидаемая, \(\bar p\) — их среднее. Важно тут не запомнить формулу, а увидеть знаменатель: \(n\) обратно пропорционально квадрату абсолютной разницы.

Сколько это в наблюдениях
Базовый CTRприрост 1%прирост 2%прирост 5%
1%15.6 млн3.9 млн637 тыс
5%3.0 млн753 тыс122 тыс
20%630 тыс158 тыс26 тыс

На группу; \(\alpha = 5\%\), мощность 80%. Числа воспроизводятся скриптом _tools/abtest_demo.py.

Два наблюдения, которые стоит унести:

  • Закон вчетверо. При базе 5% прирост 2% требует 753 тысяч, прирост 1% — 3.0 млн. Отношение 3.98: вдвое меньший эффект стоит вчетверо больше данных. Это и есть ответ на предложение «померить плюс одну десятую процента».
  • Чем реже событие, тем дороже. При том же относительном приросте падение базовой конверсии с 20% до 1% увеличивает требуемую выборку в 25 раз, потому что абсолютная разница \(p_0 \cdot \text{lift}\) стала меньше.
Обратная задача: MDE

Обычно трафик задан, и полезнее спросить, какой минимальный эффект вы вообще способны различить. При базовом CTR 5%:

Наблюдений на группуРазличимый прирост от
100 тыс5.53%
1 млн1.73%
10 млн0.55%

Считать MDE надо до запуска. Эксперимент, у которого MDE выше ожидаемого эффекта, не «покажет отсутствие эффекта» — он не покажет ничего, и это будет стоить двух недель.

Подглядывание

Соблазн понятный: тест идёт, дашборд обновляется, и хочется посмотреть, не покрасилось ли уже. Проблема в том, что уровень значимости 5% относится к одной проверке.

A/A-тест: эффекта нет вообще

Симуляция, в которой обе группы устроены одинаково, то есть истинный эффект строго нулевой. Считаем, в какой доле экспериментов критерий хоть раз пересёк порог:

Как смотримЛожных срабатываний
один раз в конце5.0%
раз в день, неделя16.5%
раз в день, две недели21.5%

20 000 повторений на конфигурацию; _tools/abtest_demo.py.

Каждый новый взгляд — ещё один шанс случайно пересечь порог. Номинальные 5% превращаются в 21%, то есть каждый пятый «успешный» эксперимент на самом деле пустой.

Что с этим делать
  • Фиксировать горизонт заранее и смотреть один раз в конце. Скучно и работает.
  • Последовательные критерии (SPRT, always-valid inference) — если смотреть по ходу действительно нужно. Они устроены так, что подглядывание разрешено по построению, ценой чуть большей выборки.
  • Alpha spending — заранее расписанный бюджет значимости по заранее назначенным точкам проверки.

Отдельно: остановка «как только покрасилось» — это подглядывание в самой вредной форме, потому что она систематически завышает оценку эффекта. Вы останавливаетесь на случайном максимуме.

Что здесь надо увидеть
  1. Вкладка размера выборки: кривая падает как \(1/\sqrt{n}\). Чтобы различить вдвое меньший эффект, нужно вчетверо больше данных.
  2. Уменьшите базовую конверсию при том же относительном приросте — требуемая выборка растёт, потому что абсолютная разница стала меньше.
  3. Вкладка подглядывания — это A/A-тест. Увеличивайте число проверок и смотрите, как доля ложных срабатываний уходит от 5% к 20 с лишним.

Что сказать на собесе: «Горизонт фиксируем заранее и считаем MDE до старта. Если надо смотреть по ходу — последовательный критерий или alpha spending, иначе номинальные 5% превращаются в 20 с лишним».

5. Когда рандомизация по пользователям ломается

Классический A/B предполагает изоляцию: то, что происходит в тесте, не влияет на контроль. В рекомендательных системах это предположение нарушается регулярно.

Где ломаетсяМеханизмЧем чинят
Двусторонние рынки
такси, маркетплейс, доставка
тестовая группа выкупает ограниченный ресурс — курьеров, товар на складе, — и контролю достаётся меньше рандомизация по городам, дарксторам, временным слотам; switchback-тесты
Социальные графы пользователь из теста активнее постит и лайкает, это видят его друзья из контроля кластерная рандомизация по компонентам графа
Общие модели система переобучается на логах обеих групп, и тестовая политика подмешивает свои данные в обучение — контроль перестаёт быть контролем раздельное обучение на данных контроля либо холдаут, исключённый из обучения

Третий случай особенно неприятен тем, что незаметен: инфраструктура A/B работает штатно, разметка корректна, а утечка идёт через переобучение. Проверяется вопросом «а на чьих логах учится модель, которую видит контроль».

6. Дисциплина эксперимента

Гипотеза формулируется до запуска

Если список метрик широкий, вы всегда найдёте что-то, что покрасилось. При двадцати метриках и уровне 5% одна ложно-значимая ожидается просто по построению.

Поэтому до старта фиксируются: конкретная проверяемая гипотеза, одна главная метрика решения, горизонт и правило остановки. Всё остальное — вспомогательные срезы для понимания, а не основания для выката.

Метрики-антагонисты

К каждой метрике роста полезно завести метрику, которая испортится, если рост достигнут неправильным способом.

  • растёт CTR — смотрим на глубину просмотра и долю быстрых возвратов;
  • растёт время в приложении — смотрим на удержание через неделю;
  • растёт GMV — смотрим на возвраты и на долю показов у топ-1% каталога;
  • растёт любая метрика — смотрим на coverage: не куплен ли рост схлопыванием в популярное.

Это тот же приём, что и в главе про контур: быстрые метрики двигают, медленные и антагонистичные — охраняют.

Вопросы с собеседований

Почему нельзя делать случайный сплит?

Потому что в данных почти наверняка есть признаки, проксирующие популярность: счётчики показов, покупок, средний рейтинг. При случайном сплите они посчитаны по всему датасету, включая тест, и уже содержат будущие клики. Модель этим пользуется, метрики выглядят прекрасно, а в проде такого признака не существует.

Правильно — глобальная отсечка по времени, причём все агрегаты и счётчики тоже считаются только по данным до неё, иначе временной сплит перестаёт быть временным.

Leave-one-out выглядит временным, но отсечка у каждого пользователя своя, поэтому агрегаты снова текут. Это известная методологическая проблема академических сравнений.

Что делать с холодными пользователями и айтемами в тестовой выборке?

Принять решение явно, потому что от него сильно зависит число. Выбросить холодных — завысить качество: в проде они есть всегда. Оставить и считать промахом — честно, но смешивает качество модели с покрытием холодного старта.

Рабочий вариант — считать две метрики отдельно, на тёплых и на холодных, плюс долю холодных как самостоятельное число. Иначе улучшение модели и ухудшение покрытия сливаются в одно движение метрики.

Зачем нужен бейзлайн популярности, если он заведомо хуже?

Он не соперник, а измерительный прибор: показывает, сколько метрики набирается вообще без персонализации. Ответ обычно неприятно высокий.

Дальше он читается как диагностика. Модель обходит популярность на проценты — вопрос о её сложности становится содержательным. Не обходит вовсе — почти наверняка ошибка в протоколе. Обходит подозрительно сильно — ищите утечку: слишком хороший результат на первом прогоне это симптом, а не успех.

Сколько трафика нужно, чтобы поймать прирост в 1%?

Зависит от базовой конверсии, и зависимость квадратичная по абсолютной разнице. При базовом CTR 5% и стандартных 5% значимости с мощностью 80% — около 3 млн наблюдений на группу. При CTR 1% — 15.6 млн. При CTR 20% — 630 тысяч.

Ключевое соотношение: вдвое меньший эффект требует вчетверо больше данных (проверено численно: 753 тыс против 3.0 млн, отношение 3.98). Поэтому предложение «померить +0.1%» обычно означает «нам не хватит трафика», и это надо посчитать до запуска, а не после.

Почему нельзя подглядывать в результаты A/B по ходу?

Уровень значимости 5% относится к одной проверке. Каждая следующая — ещё один шанс случайно пересечь порог.

На A/A-тесте, где истинный эффект строго нулевой: одна проверка в конце даёт честные 5.0% ложных срабатываний, ежедневная проверка в течение недели — 16.5%, в течение двух недель — 21.5%. То есть каждый пятый «успешный» эксперимент пустой.

Что делать: фиксировать горизонт заранее; либо брать последовательный критерий или alpha spending, где подглядывание разрешено по построению. И отдельно — остановка «как только покрасилось» систематически завышает оценку эффекта, потому что останавливаются на случайном максимуме.

Когда рандомизация по пользователям даёт смещённую оценку?

Когда нарушается изоляция групп. Три типичных случая.

Двусторонние рынки: тестовая группа выкупает ограниченный ресурс — курьеров, товар, — и контролю достаётся меньше. Лечится рандомизацией по городам, дарксторам или временным слотам, switchback-тестами.

Социальные графы: активность теста видят друзья из контроля. Лечится кластерной рандомизацией по компонентам графа.

Общие модели: система переобучается на логах обеих групп, и тестовая политика подмешивает данные в обучение — контроль перестаёт быть контролем. Самый незаметный случай, потому что инфраструктура при этом работает штатно.

Шпаргалка одним экраном

Сплит

Только временной, одна глобальная отсечка. Агрегаты — тоже слева от неё. Leave-one-out течёт.

Холодные в тесте

Две метрики отдельно плюс доля холодных. Иначе качество и покрытие сливаются.

Бейзлайн

Популярность — прибор, а не соперник. Слишком хороший результат — симптом утечки.

Размер выборки

При CTR 5%: +5% → 122 тыс, +2% → 753 тыс, +1% → 3.0 млн. Вдвое меньше эффект — вчетверо больше данных.

Подглядывание

1 проверка — 5.0%, ежедневно две недели — 21.5%. Горизонт фиксируем заранее.

Сетевые эффекты

Ресурс, граф, общая модель. Лечение: кластерная рандомизация, switchback, холдаут вне обучения.

Первоисточники