![](https://habrastorage.org/webt/6s/dd/mg/6sddmgfkwzii1vn3gkwkzqo38uk.jpeg) Упрощать и искать похожие детали, очень полезный навык! Предлагаю быстро пробежаться и попробовать найти ту самую серебряную пулю в **RecSys** ! ## Введение Постановка задачи обычно такова: у нас есть запрос и множество документов, из которых нужно выбрать наиболее релевантный. Это может быть пользователь и музыкальный трек, текстовый запрос и рекламный баннер или даже документы из одного домена. В современных системах чаще используются модели с поздним связыванием (**late interaction**): есть две независимые башни для **query** и **doc**, которые преобразуют их в вектора. Далее релевантность аппроксимируется через скалярное произведение: $\text{dotproduct}(\text{vec}_q, \text{vec}_d) \to \text{relevant}_{score}$. Это может быть клик/не клик или ручная разметка. > **Важно**: скалярное произведение не нормировано, так как качество выше, если модель сама учит регулизацию. Если грамотной регулизации нет — лучше использовать нормированые вектора(aka косинусная мера). **Почему это удобно?** - Можно независимо в оффлайне пересчитывать документы, не зависеть от рантайма. - Не нужно каждый раз пересчитывать декартово произведение (doc, query) векторов. - Можно построить KNN и искать быстро! - Универсальный интерфейс, подходящий для многих задач. - Можно эффективно считать FPS (Full Product Softmax) — ранее связывание + претраин FPS + SFT эффективнее, чем позднее связывание без FPS претраина. ## Что такое DSSM? Звучит мощно, не так ли? В 2008 году Microsoft выпустили статью [Learning Deep Structured Semantic Models for Web Search using Clickthrough Data](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/cikm2013_DSSM_fullversion.pdf), где показали DSSM (Deep Semantic Similarity Model): две башни (query, doc) и в таргете клик! С тех пор это название закрепилось за таким дизайном моделей. > Теперь ты знаешь, что значит это сокращение захватившее все продакшены бигтехов там где есть DL :D ![](https://habrastorage.org/webt/pr/gz/vc/prgzvclcskwe47q5ilio5wsekl0.png) Запросная часть обычно считается в рантайме, поэтому её делают легче, чем документную. Есть трюки для оптимизации нагрузки: кеширование, горизонтальный рост и др. Классический пример башен — трансформеры над последовательностями + MLP (для категориальных/вещественных признаков и результата трансформера). ## Ранжирующие лоссы В поиске самого релевантного документа оказывается, что абсолютные скоры не важны — важен порядок! Здесь открывается пространство для **ранжирующих функций ошибок**. > [В течении написания наткнулся на офигетельный хендбук Яндекса по рексису. Многое буду брать от туда](https://education.yandex.ru/handbook/ml/article/kontentnye-rekomendacii) **Важное наблюдение:** > Некоторые авторы пытались вместо косинусной меры использовать обучаемый MLP, но это оказалось неэффективно. ### Обозначения - $q$ , $d$ — эмбеддинги объектов - $R(q, d) = \text{dotproduct}(q, d)$ — релевантность (помним, при нормализации векторов) --- Основной трюк в обучении рекомендательных систем — сбор сэмплов из клика (обычно одного) и множества негативов (практически любой другой документ). Но использовать слишком много негативов неразумно! Здесь помогает **negative sampling** (ещё из [Word2Vec](https://arxiv.org/pdf/1402.3722)). Обычно берём 1 позитив ($d^{+}$) и $n \approx 5$–20 негативов ($d_i^{-}$). ### PointWise | Softmax Loss Классический способ — предсказывать абсолютную вероятность: $$ P(d \mid q) = \frac{\exp(R(q, d))}{\sum_{i=1}^{D} \exp(R(q, d_i))} $$ $$ \mathcal{L}(q, d^{+}) = -\log(P(d^{+} \mid q)) $$ ### Pairwise loss | PairCE + TripletLoss Теперь важно лишь, что $d^{+}$ релевантнее $d^{-}$. **Pair Cross-Entropy loss (PairCE):** $$ \mathcal{L}(R(q, d_+), R(q, d_-)) = \mathrm{CrossEntropy}(1.0, \sigma(R(q, d_+) - R(q, d_-))) $$ **Triplet loss:** $$ \mathcal{L}(R(q, d_+), R(q, d_-)) = \max(0, \alpha - R(q, d_+) + R(q, d_-)) $$ Все эти лоссы учат отталкивать разнорелевантные пары. Softmax Loss дополнительно учит предсказывать вероятность, что усложняет задачу для сетки, ведь для ранжирования это избыточно. ### ListWise | FPSLoss Часто используют PairCE/TripletLoss с одним кликом и кучей негативов — это похоже на ListWise, но можно ли придумать что-то новое? Да! В игру мощно врывается — [CLIP](https://github.com/OpenAI/CLIP?tab=readme-ov-file) (2021), решает задачу — определение семантической близости картинки и текста, где найден эффективный способ получения негативов. ![](https://habrastorage.org/webt/hx/ph/b-/hxphb-v3o2w4f_psd_ogetlxemw.png) **Full Product Softmax loss (FPSLoss):** Собираем батч размера $M$: $(q_1, d_1, r_1), \ldots, (q_m, d_m, r_m)$, где $q$ — запрос, $d$ — документ, $r$ — релевантность (обычно положительная, часто клик и равен 1). Составляем матрицу эмбеддингов запросов $U$, документов $W$ и вектор таргетов $r$. Тогда перемножение матриц — это эффективный подсчёт dotproduct, а далее и вероятностей: $$ \mathrm{softmax}(\alpha U W^{T} + \beta), \quad U W^{T} \in \mathbb{R}^{M \times M}, $$ ![](https://habrastorage.org/webt/za/ql/u3/zaqlu3dryqe_ceds7kkejoa2ddu.png) Остаётся, как и в Softmax, взять элементы только с диагонали: $$ L = -\mathbb{I}\{r > 0\}^{T} \cdot \log\left(\mathrm{diag}\left(\mathrm{softmax}(\alpha U W^{T} + \beta)\right)\right) $$ Интуитивно понятно, что учится относительная вероятность при условии query $\frac{p(\text{query}|\text{doc})}{p(\text{query})}$. Обращу внимание, что легко можно добиться смену местами query и doc. Также заметим, как хитро и качественно теперь негативы собираются! ## А что с этим делать? ![](https://habrastorage.org/webt/ux/rt/bl/uxrtbltfaxbpo-mn0wqiencqcyi.jpeg) Предлагается следующее: * Определить архитектуры башен: наверняка это должна быть комбинации [BERT](https://arxiv.org/pdf/1810.04805) + MLP * Собрать очень много данных для FPS лосса (обычно яркий положительный фидбек пользователя) * Сделать долгий претраин на FPS * Дофайнтюниться на свою задачу, если нужно Потихоньку начинаю писать в [@noisetosignal](https://t.me/+u0P_Xvm_oBcyYThi) — идёмте вместе! ## Заключение Этим хотел показать, общий вид DL RecSys и на самом деле все кроется в маленьких деталях. Абсолютно точно, для каждой задачи нужно относиться критически и замерять профит от каждого действия, что в рексисе является очень не простой задачей! --- *Если статья была полезна — ставьте лайк, подписывайтесь и делитесь своим опытом в комментариях!*