← к модулям

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

Откуда вообще берутся обучающие данные в 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) — это то, что человек реально видел и не выбрал. Полная коррекция экспозиции (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 (те же фичи на обучении и в проде) и мониторинг.