Данные и логирование

Откуда вообще берутся обучающие данные в RecSys: event log → лейблы, позиционное смещение и петля обратной связи. Самое важное в этом модуле — не модель, а понимание, как устроены данные, на которых всё держится.

⚠ Лог здесь синтетический (реальны только названия фильмов): у MovieLens нет impression/click-логов. Настоящие behavior-логи — на следующем implicit-feedback датасет-треке.

1 · Лог событий и позиционное смещение

Синтетический лог показа: каждая сессия показывает топ-выдачу, клики возникают по position-based модели (увидел × привлекательность). CTR падает с позицией — но падает он по двум причинам сразу: реже смотрят вниз и наверх поставлены лучшие айтемы. Разделить их можно только рандомизацией — обе кривые ниже.

2 · Конструктор лейблов

Лейбл — это продуктовое решение, а не данность. Один и тот же лог под разным определением цели даёт разный размер выборки и долю позитивов.

3 · Петля обратной связи (rich-get-richer)

Обучаем тривиальную модель на наивных кликах и переранжируем — раунд за раундом. Без exploration экспозиция схлопывается на том, что случайно всплыло наверх, и хорошие айтемы так и не получают показов. ε (exploration) — противоядие.

Теория простым языком

Самый недооценённый вопрос в RecSys: откуда берутся обучающие данные? Модель учат не на «рейтингах из датасета», а на логах поведения — что показали, что кликнули, что досмотрели, что купили. Как превратить поток событий в обучающую выборку — и какие ловушки тут спрятаны — и есть тема этого модуля.

Событие, импрешн, лог

Event log — поток событий рекомендера: каждый показ, клик, просмотр, покупка — строка с контекстом (кто, что, где, на какой позиции, когда, какой моделью показано).
Impression (показ) — факт, что айтем был показан пользователю на конкретной позиции. Без лога импрешнов мы не знаем, что человек вообще видел — а это критично (см. ниже).
Viewable / examined impression — в проде «показ» уточняют: айтем не просто был в ответе сервера, а реально попал в область видимости (viewport) и пользователь успел его рассмотреть. Цепочка строже, чем кажется: в ответе сервера → во viewport → рассмотрен → взаимодействие. Иначе можно записать «показ», которого человек физически не видел — и тогда no-click ≠ dislike вдвойне. В симуляторе выше вероятность examination (падающая с позицией) — это и есть модель того, был ли импрешн рассмотрен.

Минимальная схема таблицы events: request_id, session_id, user_id, item_id, event_type (impression/click/watch/purchase), position, surface, model_version, experiment_id, timestamp. Выше на странице — живой синтетический лог по этой схеме.

▸Почему RecSys начинается не с модели, а с логов
БылоВ учебных датасетах ratings/interactions уже даны готовыми.
ПроблемаВ проде лейблов нет — их надо собрать из потока событий.
ИдеяЛогировать impressions, clicks, watches, purchases + позиции и timestamps.
Стало лучшеПоявляется из чего строить обучающие лейблы и чем диагностировать смещения.
Осталось слабымClick ≠ satisfaction, no-click ≠ dislike, no-impression ≠ negative — сигнал грязный и смещённый.
ДальшеImpression-aware негативы, честный протокол оценки — temporal split; counterfactual/IPS — в следующих модулях.

Из событий — обучающая выборка

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

События → (фичи, label)
CTR-лейбл:    строки = импрешны;  label = был ли клик
CVR-лейбл:    строки = клики;     label = была ли покупка
watch-лейбл:  строки = клики;     label = досмотр ≥ T секунд
rating≥4:     строки = оценки;    label = оценка ≥ 4   (это MovieLens)
next-item:    строки = сессии;    label = следующий кликнутый айтем

Покрути «конструктор лейблов» выше: одни и те же события под разным определением дают разный размер выборки и долю позитивов.

Attribution window (окно атрибуции) — для отложенных событий (покупка, досмотр) важно, за какой период после показа/клика мы засчитываем лейбл: purchase в течение 1 дня / 7 дней / той же сессии, watch ≥ T в той же сессии. Без окна легко получить leakage (привязали покупку, случившуюся сильно позже и по другой причине) или потерять настоящий конверт. В нашем симуляторе purchase/watch происходят сразу в той же сессии (attribution = same-session) — в реальном проде окно надо задавать явно.

Главные «≠» (ради них всё затевалось)

rating ≠ click — оценка — отрефлексированное мнение; клик — импульс. Разные сигналы.
click ≠ satisfaction — кликнул из любопытства ≠ остался доволен (кликбейт).
watch ≠ качество — досмотрел ≠ контент хороший (автоплей, фон).
purchase ≠ ценность — купил ≠ долгосрочная польза/удержание (возвраты, разочарование).
no-click ≠ dislike — не кликнул ≠ не нравится (не заметил, не та позиция).
no-impression ≠ negative — не показали ≠ отрицательный пример — мы просто не знаем.

Почему нельзя наивно учиться только на кликах

Клики — полезный, но смещённый прокси (не «клики плохие»). Они смещены экспозицией и позицией: верхние позиции собирают клики просто потому, что их видят чаще. Если наивно взять «кликнутое = позитив, всё остальное = негатив», модель выучит позицию и популярность, а не вкус — и в петле обратной связи начнёт сама себя усиливать.

Exposure / position bias — вероятность клика = вероятность увидеть (падает с позицией) × привлекательность айтема. Логи кликов перемешивают эти два множителя — и без импрешнов их не разделить.
Пример. В симуляторе «петли обратной связи» выше: наивное обучение на кликах за один раунд схлопывает экспозицию на топ-20% каталога (head-share ~0.23 → ~0.80), и система застревает на «середняках», так и не показав по-настоящему привлекательные айтемы. Включи exploration (ε) — экспозиция разъезжается обратно, и хорошие айтемы получают шанс.
▸Почему impression-aware негативы ближе к наблюдаемому, чем наивные

Наивный негатив «весь каталог минус клик» раздувает выборку мусором: туда попадают айтемы, которые пользователю вообще не показывали. Ближе к делу негативы из показанного-но-не-кликнутого (impression-aware). Но и они не «то, что человек посмотрел и отверг»: сервер знает только, что ответ с айтемом был отправлен. Попал ли айтем во вьюпорт, дошёл ли до него взгляд, рассмотрел ли его человек — из served impression не следует, и именно поэтому такой негатив шумный. Честность здесь относительная: impression-aware ближе к наблюдаемому, чем каталог целиком, а полная коррекция экспозиции (IPS / counterfactual) — отдельная тема (Фаза 14).

Сильные стороны

  • Логи событий — единственный источник правды о реальном поведении (не лабораторные оценки).
  • Из одного лога — много задач (CTR/CVR/watch/next-item) под разные продуктовые цели.
  • Impression-логи позволяют строить честные негативы и корректировать смещения.

Слабые стороны

  • Клики смещены позицией/экспозицией — наивные лейблы учат артефактам показа.
  • Прокси-метрики врут: click/watch/purchase ≠ удовлетворённость/ценность.
  • Петля обратной связи: модель видит только то, что сама показала (selection bias).

⚠️ Что может пойти не так

  • Нет impression-логов → нельзя отличить «не понравилось» от «не показали»; негативы становятся мусором.
  • Лейбл = прокси: оптимизируя CTR, легко выучить кликбейт; нужны guardrail-метрики и долгосрочные сигналы.
  • Позиционное смещение: верхние слоты собирают клики за счёт видимости, а не релевантности.
  • Feedback loop без exploration: rich-get-richer, long-tail и новинки голодают.
  • Утечка времени: лейбл нельзя строить из будущего относительно фич (см. модуль про валидацию).
Пример. Что упрощено здесь. MovieLens — это оценки, без импрешнов/позиций/сессий. Весь лог на этой странице синтетический (реальны только названия фильмов) — чтобы показать механику. Настоящие behavior-логи появятся на implicit-feedback треке (следующий датасет).

🧠 Проверь себя: Почему «не показанный айтем» нельзя считать отрицательным примером?

Где это в жизни

В любой продакшен-системе (YouTube, маркетплейсы, ленты) обучение крутится вокруг логов показов и взаимодействий, а не «оценок». Качество данных и лейблов решает больше, чем выбор модели — поэтому это первый модуль инженерного трека. Дальше: корректная валидация (никакой утечки времени), feature store (те же фичи на обучении и в проде) и мониторинг.

Что дальше

Можно читать параллельно — тот же блок, порядок между ними не важен

До финальной сборки не хватает ещё 12 модулей по этому пути.

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

Источники