OneRanker: Unified Generation and Ranking with One Model in Industrial Advertising Recommendation [2/3]
В прошлом посте приступили к разбору статьи о том, как в три шага объединить генерацию кандидатов и ранжирование в одной модели. Начали с проблематики и первого шага фреймворка, сегодня продолжим обсуждать второй шаг.
Шаг 2. Учёт задач и кандидатов (multi task/target aware)
Разделение задач. Авторы вводят task tokens:
• по одному на каждую задачу, связанную с действиями пользователя (например, показ, клик или конверсия);
• отдельный для бизнес-ценности.
Они используют общее представление истории, но связаны с разными выходными головами. Токены упорядочены, например: показ → клик → конверсия → ценность. Каузальная маска позволяет поздним токенам учитывать ранние; ранние не видят поздние при attention.
Fake Item Tokens. Авторы кластеризуют эмбеддинги объектов методом K-means и используют как токены центры кластеров (в статье используют 32 кластера). Это ориентиры в пространстве объектов, а не реальные кандидаты. Они дают генерации приближённую информацию о том, какие области этого пространства важны для пользователя в конкретной задаче.
Взаимодействие токенов. Task tokens и Fake Item Tokens сначала обращаются к представлениям истории из шага 1 через cross-attention, затем взаимодействуют через self-attention. Маска разрешает обмен между токенами задач и центров, но не между разными центрами.
Два канала представления. Для каждой задачи модель сохраняет семантический вектор её task token. Второй канал строится из пар этого токена с каждым Fake Item Token: пары проходят через MLP, а результаты суммируются. Получается сигнал о предпочтениях пользователя по областям пространства объектов в рамках данной задачи. Оба канала объединяют в представление пользователя.
Представление айтема строится симметрично: к его эмбеддингу добавляют косинусное сходство с каждым центром кластера. Скалярное произведение представлений пользователя и айтема даёт скор отбора. Он складывается из семантического соответствия задаче и соответствия по центрам: насколько айтем близок к областям, важным для пользователя.
Уточнённые представления шага 2 подаются в MTP для генерации кандидатов. На шаге 3 эти кандидаты получат отдельные скоры ранжировщика.
Шаг 3, обучение и результаты экспериментов обсудим в заключительном посте.
OneRanker: Unified Generation and Ranking with One Model in Industrial Advertising Recommendation [1/3]
Сегодня приступаем к разбору статьи о том, как объединить генерацию кандидатов и ранжирование в одной модели. Начнём с проблематики и первого шага фреймворка OneRanker.
У современных рекомендательных подходов есть несколько минусов:
• Конфликт интереса пользователя и ценности для бизнеса. Генерация кандидатов опирается на клики и конверсии в истории пользователя, но системе важно учитывать и ценность объектов для бизнеса (например, для рекламы это eCPM). Если напрямую обучать генератор на обеих целях, они тянут общее представление в разные стороны: ухудшается и охват интересов, и отбор ценных объектов. Если же учитывать ценность только при ранжировании, лучшие по этому критерию кандидаты могут отсеяться раньше, чем начнётся ранжирование.
• Нечувствительность к кандидату (target-agnostic). При генерации представление пользователя одинаково для разных кандидатов. Поэтому модель не может выделить в истории именно те события, которые важны для оценки конкретного объекта.
• Разрыв между этапами. Отдельные генератор и ранжировщик могут повторно обрабатывать одну историю и учить разные представления.
Чтобы решить эти проблемы, авторы предлагают интегрировать генерацию в ранжирование на архитектурном уровне. Так появился фреймворк OneRanker. Он состоит из трёх шагов.
Шаг 1. Основа генерации
OneRanker опирается на предыдущую работу Tencent — GPR. История пользователя представлена последовательностью разнородных токенов: пользователя (U), контента (C), контекста (X) и объектов (I). Декодер на основе HSTU обрабатывает эту последовательность, а авторегрессионный механизм multi-token prediction (MTP) позволяет за один проход модели параллельно строить несколько полных цепочек семантических ID.
Что происходит на втором шаге фреймворка, подробно разберём в следующем посте.