Человек, который пользуется интернетом, часто начинает решение своих задач с поиска. Поисковая система по запросу помогает найти самую полезную для пользователя информацию, будь то поиск видео или научных статей. Для решения такой задачи необходимо отсортировать по полезности имеющуюся в базе информацию и выдать самую необходимую. Обычно такую сортировку называют ранжированием, полезность — релевантностью, а соответствующую задачу — задачей ранжирования.
Опишем задачу формально и введём обозначения.
Задача: Отсортировать документы внутри по убыванию релевантности запросу.
Уже по формулировке задачи видно, что построение решения разбивается на несколько стадий. Сначала нужно сформировать набор кандидатов , а уже потом строить финальную сортировку. Подробнее об этом в разделе про методы ранжирования.
Примеры
WEB-поиск
Классический пример задачи ранжирования — поиск информации в интернете. Пользователь задаёт запрос, и под этот запрос формируется выдача, в которой сайты (документы) расположены по убыванию полезности. В наших обозначениях:
Чтобы решать задачу ранжирования с помощью машинного обучения, необходимо иметь датасет с оценками асессоров. Обычно по парам (запрос, документ) собирают данные о том, насколько документ релевантен запросу. Такие оценки называются метками релевантности.
Поиск синонимов
Задача подбора синонимов по слову тоже может восприниматься как задача ранжирования, поскольку похожесть слов друг на друга — неоднозначное свойство, и некоторые пары слов больше похожи, чем другие. Поэтому можно сортировать слова по похожести на слово из запроса. Если — доступный словарь, то:
Для построения моделей можно использовать датасет пар синонимичных слов. Обучив модель классификации, обычно мы получаем предсказатор вероятности положительного класса. Отсортировав слова по предсказанной вероятности синонимичности, мы решим задачу ранжирования.
Рекомендательная система
Рекомендательные системы встроены во многие онлайн сервисы. Если вы заходите на сервис с фильмами, система порекомендует фильмы для вас, если в социальную сеть — посты или новые видео, которые вас заинтересуют. Это тоже отбор самых полезных объектов, но «запрос» в данном случае — это сам пользователь.
Для решения задачи построения рекомендаций используются свои методы, они рассмотрены в отдельной главе.
Метрики качества ранжирования
Предположим, мы решили задачу ранжирования. Обычно это делается обучением некоторой функции от запроса и документа ( — это параметры модели). Если такая функция готова, то выдача по запросу получается сортировкой множества по убыванию .
Здесь и далее, не нарушая общности, будем считать, что мы решаем задачу WEB-поиска. Выберем множество тестовых запросов , на которых оценим качество нашего решения.
Для формул метрик качества введём следующие обозначения:
Соответственно,
Бинарная релевантность
Величина, которая обозначает, насколько документ подходит запросу, называется релевантностью. Способов измерить эту величину много. Обычно решение о том, релевантен документ запросу или нет, принимают асессоры — специальные люди, которые размечают данные для обучения ML-моделей. Собранные оценки называются метками релевантности, будем обозначать метку для запроса и документа за .
Для начала введём метрики для случая бинарной релевантности, когда .
Precision / Recall
Если у релевантности есть всего 2 класса, то можно вспомнить метрики классификации и обобщить их для задачи ранжирования.
Будем считать, что ранжирующая модель считает релевантными те документы, которые попали в первые элементов выдачи, то есть . Тогда можно вычислить метрики precision и recall в зависимости от .
В случае с recall приходится брать минимум в знаменателе, поскольку в такой постановке модель не может выявить больше, чем релевантных документов.
Mean Average Precision
Заметим, что метрики precision и recall хоть и показывают качество нашей ранжирующей системы, но совсем не смотрят на порядок элементов в . Чтобы его учесть, посмотрим на Precision по тем позициям, где стоят релевантные документы, и усредним их. Такая величина называется Average Precision.
Теперь, чтобы получить труднопереводимую на русский язык метрику Mean Average Precision, нужно усреднить значения AP по всем запросам из набора.
Mean Reciprocal Rank
Название этой метрики переводится как средний обратный ранг. Ранжирование работает тем лучше, чем ближе к началу выдачи релевантный для пользователя документ. Для каждого запроса найдём позицию первого релевантного документа, возьмём обратное от этого числа и усредним по всем запросам.
Обозначим релевантность -го документа в выдаче как .
Тогда формулу можно переписать в следующем виде:
Произведение в формуле будет равно только в случае, когда документ релевантный, а все до него нет. В остальных случаях произведение равно .
Вещественная релевантность
Рассмотрим теперь метрики для случая, когда релевантность может принимать вещественные значения.
Expected Reciprocal Rank
Пусть теперь — вероятность того, что документ релевантен. Например, если — метка релевантности, а — максимальное её значение, то можно определить .
Будем считать, что пользователь листает выдачу документ за документом. В каждом он находит информацию, которая ему нужна, с вероятностью . Если информацию он нашел, то он заканчивает поиск.
В такой модели хорошая система позволит пользователю найти информацию как можно быстрее. Но в отличие от бинарной релевантности позиция, где пользователь закончил поиск, теперь случайная величина, как и обратная позиция. Поэтому будем считать матожидание этой величины.
Если пользователь остановился на позиции , это значит, что на предыдущих документах задачу он не решил, а остановился именно на -ом. В модели эти события предполагаем независимыми, поэтому вероятности можно перемножить.
Чтобы получить финальную метрику, усредняем эту величину по всем запросам.
Заметим, что формула совпала с формулой для метрики MRR для бинарной релевантности.
pFound
Рассмотрим ещё одну метрику, которая основывается на модели поведения пользователя. Метрика pFound была придумана в Яндексе и некоторое время была основной для ранжирования.
Пусть релевантность задаётся одним из классов
По историческим данным считаются соответствующие вероятности найти нужное в документе в зависимости от класса
Отличием от предыдущей модели является введённая константа — вероятность бросить искать информацию и листать выдачу.
Посчитаем вероятность того, что пользователь дошёл до позиции . Для этого он должен дойти до документа на позиции , не устать искать, и при этом не найти нужного в предыдущем документе. Опять же перемножаем вероятности.
Теперь — это вероятность найти нужное в выдаче
Чтобы теперь посчитать финальную метрику, усредняем по всем запросам в тестовом множестве .
nDCG
Введём метрику DCG (Discounted Cumulative Gain).
Будем считать, что релевантный документ в топе приносит некоторую пользу (gain) в зависимости от своей релевантности. При этом до низкого документа в выдаче могут и не долистать, поэтому он приносит меньше пользы, то есть она уменьшается. Будем дисконтировать пользу в зависимости от позиции (discount).
Здесь — функция пользы, а — функция дисконтирования от позиции. Для этих функций возможны разные вариации, рассмотрим классический и упрощённый.
Классический вариант:
Упрощённый вариант:
Иногда при реализации поисковой системы может быть понимание, как падает внимание пользователя с ростом позиции в зависимости от типа запроса. В этом случае функция дисконтирования может стать запросозависимой.
Однако низкое значение метрики не всегда означает, что ранжирование отработало плохо. Могло быть так, что по запросу просто нет релевантных документов, или же их очень мало. Чтобы избавиться от этой проблемы, значение нормируют на эту метрику при идеальном ранжировании, когда документы отсортированы по истинным значениям релевантности.
Как и всегда, для получения метрики по набору запросов, считают среднее значение
Дополнительные метрики
Другие сигналы и экосистема
Описанные выше метрики были введены для агрегации релевантности документов в топе выдачи. Но те же рассуждения и формулы могут быть применены для других сигналов, сопоставляющих запрос и документ. Вы можете придумать любую инструкцию для асессоров и собрать разметку под вашу задачу. Одним из полезных сигналов может быть свежесть документа, которую можно понять и по времени создания документа.
Обычно в противовес релевантности смотрят на кликабельность элементов выдачи. Поисковым системам интересно получить больше кликов пользователей, тем не менее могут встречаться «кликбейтные» документы, которые побуждают кликать, но не решают на самом деле задачу пользователя. Кликабельность можно замерять как DCG предсказатора вероятности клика.
Также важно следить за чистотой выдачи. Нужно не допускать в топ мошеннические документы, шокирующие документы и документы 18+ в поиске для детей. В качестве метрики можно замерять DCG или MAP «плохих» документов в топе.
Разнообразие и метрики рекомендаций
Бывает полезно следить за тем, как документы в топе соотносятся друг с другом. В частности, нужно не допускать, чтобы все документы выдачи были с одного хоста и чтобы в них не было написано одно и то же. Для этого используются алгоритмы группировки и дедупликации.
Также, если рассматривать поиск как решение задачи рекомендации документов, можно измерять метрики новизны и serendipity, про которые подробнее рассказано в главе о рекомендательных системах.
Методы обучения ранжированию
Рассмотрим некоторую модель , по предсказаниям которой мы будем сортировать документы по запросу (здесь — это параметры модели). Мы хотим обучить модель так, чтобы у неё было оптимальное значение одной из метрик ранжирования, например, NDCG. Заметим, что если совсем немного поменять , то предсказания модели изменятся тоже несильно. Но небольшие изменения в предсказаниях могут не привести к изменению порядка документов. Тогда не изменится и метрика NDCG. Получается, что NDCG как функция от параметров является кусочно постоянной, поэтому нельзя оптимизировать её напрямую.
Наша дальнейшая задача — представить методы, позволяющие получить модель, оптимальную по NDCG или другой аналогичной метрике ранжирования.
Методы обучения ранжированию обычно делят на 3 типа:
Поточечный (pointwise) подход
В этом подходе у нас известны некоторые оценки релевантности каждой пары запрос-документ, и модель учится предсказывать эти оценки. Взаимоотношения между разными документами внутри не рассматриваются.
Попарный (pairwise) подход
Здесь во время обучения используют тройки , где — документы из , причём релевантнее по запросу . При этом модель всё равно может давать предсказания релевантности по паре .
Списочный (listwise) подход
В данном подходе для обучения используются перестановки документов из . Например, асессорские оценки дают наилучшую известную сортировку. Для её получения нужно сначала показать на выдаче докумены с самой высокой оценкой, затем со следующей по порядку и т.д.
Будем рассматривать каждый из подходов по очереди.
Поточечный подход
Сведение к регрессии и классификации
Рассмотрим простейшую постановку задачи, в которой у нас есть набор запросов , для каждого запроса имеется набор документов , который необходимо отсортировать, а в качестве обучающей выборки известны асессорские оценки релевантности для некоторых пар запрос-документ . Будем обозначать множество возможных оценок , конкретную оценку — .
Пусть — множество действительных чисел. Тогда мы можем обучить любую модель регрессии на признаках пар для предсказания оценок асессоров. Это может быть и линейная модель, и градиентный бустинг, и нейронная сеть. Обучать модель можно, например, оптимизируя MSE:
Аналогично можно сводить задачу к классификации, если метки релевантности бинарны или категориальны. Например, при шкале . Оптимизировать в данном случае можно кросс-энтропийную функцию потерь.
PRank
В случае классификации мы учим модель разделять классы, но никаким образом не задаём, что на метках имеется порядок. Мы не даём алгоритму никакой информации о том, что метка 4
находится между метками 5
и 3
и наоборот. Чтобы побороть эту проблему, была придумана модификация линейной модели, которая получила название PRank и была описана в статье Pranking with ranking.
Если предположить, что метки релевантности — это целые числа от до , то есть , то можно ввести пороги для значений ранжирующей функции, которые разделяют классы друг от друга.
В качестве ранжирущей функции возьмём обычную линейную, то есть , где — вектор признаков. Обозначим через границы классов. Они будут изменяться в процессе обучения. Также фиктивно введём .
Чтобы предсказать класс, будем искать первую границу, которая больше вычисленной линейной функции:
Коротко опишем процесс обучения. Представим, что мы получили очередной объект и вычислили линейную функцию . Отметим на оси её значение и границы классов:
Если предсказан ранг 1
, а правильный класс для объекта 4
, то необходимо, во-первых, обновить вектор , а во-вторых, сдвинуть границы других классов в сторону получившегося предсказания.
После осуществления сдвигов, предсказание на точке из обучающей выборки становится ближе к правильному.
Мы не будем приводить конкретные формулы для обновления обучаемых параметров; вы можете посмотреть их в статье.
Попарный подход
Начнём рассмотрение попарного подхода. Чтобы его применить, нужен датасет, состоящий из троек , где , причём известно, что по запросу документ релевантнее, чем . Будем обозначать такое соотношение .
Замечание. Такие данные можно собирать с использованием асессорской Side-by-Side разметки, в которой асессоры отмечают, какой из двух предложенных документов релевантнее по заданному запросу. Также можно собирать данные с помощью пользовательских логов. Например, если пользователь пролистал первые 3 документа по запросу , а решил свою задачу только на 4-ом, можно считать, что первые 3 документа были хуже. Пользовательских логов достаточно много, с их помощью можно обучать разные модели для ранжирования на основе кликов. Но надо помнить, что совсем не всегда те документы, на которые первоначально хочется кликнуть, релевантны и содержат необходимую информацию. Чтобы учесть это в модели, можно рассматривать только клики, после которых пользователь надолго остался на странице. Дополнительно можно смешивать модели на кликах с моделями на оценках асессоров, что поможет избежать проблемы смещения обучающей выборки в текущее ранжирование. Поясним, из-за чего может возникнуть эта проблема. Логи строятся по результатам взаимодействия пользователя с нашей ранжирующей моделью, и может оказаться так, что обучающая выборка будет состоять только из документов, уже попавших в топ выдачи.
Классификатор на тройках
В качестве самого простого решения снова рассмотрим сведение задачи ранжирования к уже известным задачам машинного обучения. А именно, будем решать задачу классификации троек . В качестве целевой переменной запишем , если лучше документ , и , если лучше . Собрав признаки для каждой тройки, можем обучить любой классификатор. Для этого можем взять и нейронную сеть, и линейную модель, и методы на основе деревьев.
Чтобы отсортировать документы внутри по запросу , можем воспользоваться стандартным алгоритмом сортировки с компаратором, задаваемым предсказаниями нашего классификатора.
Проблема в том, что компаратор должен быть как минимум транзитивным. Гарантировать такое свойство для большинства моделей машинного обучения мы не можем.
RankingSVM
Но если ввести модель специальным образом, можно гарантировать транзитивность предсказаний. Снова воспользуемся линейной моделью.
Задача. Найти вектор весов , для которого было бы выполнено . Здесь , – векторы признаков для пар и соответственно.
Так как требуется выполнение неравенств вида , где — вектор поэлементной разницы признаков, можно обучить линейную модель на парах, где признак пары – это как раз вектор .
Если в качестве модели взять SVM, получится классический метод обучения ранжированию, который называется RankingSVM.
Чтобы сравнить 2 документа по запросу, надо сравнить с нулём. Получается, что для двух одинаковых документов это выражение всегда . Кроме того, выполнена требуемая от компаратора транзитивность.
RankNet
Пусть имеется обучающая выборка, в которой известны метки релевантности для пар запрос-документ.
Введём модель для ранжирующей функции , дифференцируемую по . Например, это может быть линейная модель или нейронная сеть. Также возможно применение композиций деревьев. Ниже мы будем описывать оптимизационную процедуру для моделей, которые обучаются с помощью градиентного спуска; для деревьев потребуются другие методы.
Будем рассматривать события , то есть события вида «документ релевантнее по запросу ».
Из разметки асессоров мы можем задать вероятности таких событий.
Если асессорских оценок на каждый документ несколько, можем по-разному агрегировать эти оценки в . Если же доступна попарная разметка (какой из документов и релевантнее запросу ), то вероятностью можно назвать долю оценок, в которых признан лучше, чем .
Далее введём оценку вероятности этого события, порождённую моделью.
Для пары рассмотрим случайную величину
Согласно асессорам, . Согласно модели, . Задача обучения в том, чтобы уравнять эти два распределения между собой для всех пар документов. Поэтому в качестве функции потерь будем использовать KL-дивергенцию. Введём для каждой пары лосс
Тут – энтропия, не зависящая от , а значит и от параметров модели .
Для определённых выше выполнены следующие свойства:
Видно, что для двух документов с разными истинными метками релевантности такой метод обучения штрафует модель за одинаковые предсказания. Это свойство очень полезно, поскольку в случае одинаковых предсказаний непонятно, в каком порядке располагать документы.
Полная функция потерь выглядит следующим образом:
Минимизировать её можно при помощи градиентного спуска или различных его модификаций.
Вычислим производные функции потерь по .
Пусть . Тогда:
то есть .
Подставим полученное выражение в производную функции потерь по весам.
Аналогично получаем выражения для остальных случаев соотношения между и .
Определим теперь
Тогда получаем
Итерацию градиентного спуска теперь можно записать в более простом виде:
Таким образом, мы можем делать SGD не по парам документов, а по отдельным документам. Это увеличивает скорость сходимости.
Получается, что зависит от номера документа и от попарных разностей скоров модели на документах , при этом не зависит от производных самих по параметру . Введённые можно представить в виде стрелок, которые прикреплены к каждому документу в поисковой выдаче. Направление стрелки означает, куда мы хотим перенести документ, чтобы выросла нужная метрика, а длина – насколько сильно.
LambdaRank
Задача этого метода в том, чтобы соединить RankNet и наше желание напрямую оптимизировать введённые ранее кусочно постоянные метрики качества, например, NDCG. Обозначим через значение этой метрики для запроса при ранжировании функцией . Попытаемся придумать гладкую попарную функцию потерь
где
оптимизация которой была бы эквивалентна оптимизации .
Заметим, впрочем, что для обучения сама нам не нужна, а нужны только производные, которые, как и в случае RankNet, можно записать в виде
В данном случае мы хотели бы задать специальным образом: так, чтобы сдвиг в направлении антиградиента вёл к уменьшению метрики . Ясно, что не любое выражение для может задавать градиент. Чтобы проверить существование функции потерь , применим следующий частный случай леммы Пуанкаре:
Лемма. Пусть – функции, такие что
Тогда существует функция , такая что .
Значит, нужно ввести лямбды таким образом, чтобы совпадали смешанные производные.
Определим – функцию релевантности, в которой поменяли местами и :
Обозначим также через приращение метрики при перестановке местами и . В методе LambdaRank определяется следующим образом:
где – некоторая константа. Множитель кусочно постоянен, так что не повлияет на градиент.
Вопрос на подумать. Проверьте, что для указанных действительно выполнено условие леммы Пуанкаре.
Авторы метода проверяли его для оптимизации NDCG. Они пытались случайными сдвигами параметра улучшить NDCG после оптимизации через LambdaRank. Доля успешных сдвигов оказалось очень мала, так что экспериментально подтверждается успешная оптимизация этим методом недифференцируемых метрик ранжирования.
LambdaMART
Этот метод является конкретной реализацией подхода LambdaRank. В нём для предсказания строится модель градиентного бустинга на решающих деревьях.
Каждое дерево обучается на градиент функции потерь предыдущей итерации алгоритма (и градиент мы как раз умеем считать, хотя саму функцию потерь – нет). Структура дерева определяется жадными по MSE разделениями.
При этом размер шага (коэффициент, с которым берётся значение в следующем дереве) задаётся не один для всей модели, а подбирается во всех листах каждого дерева при помощи метода Ньютона.
Более подробно о последних трёх методах можно почитать в оригинальной статье от Microsoft: From RankNet to LambdaRank to LambdaMART.
Списочный подход
SoftRank
Вспомним, что основной проблемой, из-за которой невозможно оптимизировать NDCG и похожие метрики напрямую, является их кусочная линейность. Идея метода SoftRank — сгладить метрику, чтобы при небольших изменениях параметров модели она тоже изменялась. Для этого оценку релевантности документа будем рассматривать не как константу, а как случайную величину.
Сглаживание метрики рассмотрим на примере. Пусть имеются документы , , для запроса , а ранжирующая модель дала им соответственно оценки релевантности , , . Тогда, если это случайные величины, то они константны и их распределение вырождено. В связи с этим порядок документов на выдаче тоже определён однозначно, и первое место занимает документ с наибольшей оценкой.
Чтобы поменять метрику, будем считать, что оценка релевантности документа по нашей модели имеет распределение , где — гиперпараметр метода. Чтобы отсортировать документы, будем генерировать число из этого распределения и ранжировать по нему. Тогда может случиться так, что документ с самым большим окажется на последнем месте. Но с наибольшей вероятностью он всё равно будет первым. И распределение позиций документов на выдаче будет выглядеть примерно так:
Теперь, чтобы получить метрику, осталось только в формуле NDCG заменить дискаунт на его математическое ожидание.
Можно заметить, что теперь небольшие сдвиги параметров будут менять распределение позиций документов, а значит и будет изменяться. Поэтому функция становится дифференцируемой, и её можно использовать как функцию потерь. При этом для того, чтобы вычислить распределение рангов, необходимо использовать отсортированный список документов. А значит, хоть напрямую оптимизируемый функционал и не зависит от перестановок, этот метод можно отнести к списочному подходу.
Подробнее об этом методе можно прочитать в статье.
ListNet
Следующие 2 метода, которые мы рассмотрим, работают с перестановками документов для одного запроса. Если заданы оценки релевантности , для запроса , то они формируют распределение на перестановках.
Пусть дана перестановка . Определим её вероятность следующим образом:
Такая вероятностная модель называется моделью Люcа-Плакетта.
Для примера рассмотрим 3 документа и оценки . Тогда вероятность перестановки запишется так:
Аналогично методу RankNet, мы имеем распределение, которое можно сформировать из оценок асессоров и из оценок модели . А значит можно в качестве функции потерь использовать KL-дивергенцию между этими распределениями.
где — параметр модели.
Однако различных перестановок получается , а значит, даже чтобы просто вычислить дивергенцию Кульбака-Лейблера, потребуется немало времени, не говоря уже про оптимизацию этой функции потерь.
Поэтому вместо того, чтобы рассматривать вероятность полной перестановки, смотрят на распределение индекса первого документа на выдаче.
Оптимизируют KL-дивергенцию между этими распределениями:
ListMLE
В этом методе рассматривают вероятность одной «правильной» перестановки. В данном случае под правильной перестановкой понимается та, которая получается, если упорядочить документы из по убыванию асессорских оценок . Логично, что хорошая модель должна давать большую вероятность такой перестановке, поэтому именно она и максимизируется.
Всё сводится к поиску оценки максимального правдоподобия, поэтому метод и называется ListMLE.
Практические советы
Популярные признаки
Выше показано, как можно построить модель, если уже известны признаки для пар запрос-документ , а также, как можно собрать целевые переменные для обучения. Но какие стоит взять признаки, чтобы получить хорошую модель?
Признаки для моделей ранжирования можно разделить на 3 типа: запросные, документные и запросно-документные. Первые зависят только от запросы, вторые только от документа, а третьи от всей пары, то есть для их вычисления необходимо сопоставить запрос и документ.
Конечно, наибольший интерес представляют запросно-документные факторы. Но и другие группы факторов могут быть полезны.
Запросными являются, например, следующие факторы:
- Количество слов в запросе
- Язык запроса
- Страна, из которой задали запрос
- Значение классификаторов
Многие модели могут подстроиться под эти факторы и отдельно обучиться под различные значения запросных признаков. Например, так модель может по-разному реагировать на запросы из разных стран.
TF-IDF
Чтобы сопоставить запрос и документ, можно использовать TF-IDF слов запроса. Например, можно просуммировать его по всем словам из запроса и получить фактор для ранжирования. Подробно о том, как считать TF-IDF, можно прочитать в главе про NLP.
DSSM и другие нейросетевые факторы
Запросно-документные факторы можно получать, «соединяя» векторные представления запроса и документа. Классическим способом такого соединения является простой подсчёт косинуса угла между векторами.
Если обучить модель, которая для пар, где документ релевантен запросу, выдаёт вектора, похожие на сонаправленные, то скалярное произведение становится оценкой релевантности. Если оно близко к единице, векторы сонаправлены, а значит документ подходит запросу. При этом обычно нормируют векторы на выходе, чтобы косинус и скалярное произведение были одним и тем же.
В качестве модели эмбеддинга можно использовать полносвязную нейронную сеть. На вход такой сети можно подать BagOfWords вектор или же вектор TfIdf. Эти векторы большой размерности нейросеть преобразует в меньшие. Обычно размер выходного слоя выбирают, балансируя между качеством и ресурсами, необходимыми на расчёт и хранение выхода сети.
Этот подход был назван Deep Structured Semantic Models
и описан в статье от Microsoft. Идею можно применять в целом в любой задаче ранжирования для своих типов «документов».
Посмотреть, как она была воплощена в Web поиске для поиска по смыслу, можно в блоге Яндекса. Если вкратце, у модели следующие особенности:
- На входе у модели не все тексты, а только заголовок документа и запрос;
- Для уменьшения размера входа текст разбит на буквенные триграммы, вектор на входе - это Bag Of Trigrams;
- Архитектура обработки запроса и документа разная;
- Особый способ генерации негативных примеров.
Схематически архитектура модели показана на рисунке ниже:
Конечно, чтобы заставить простую архитектуру давать хорошее качество, нужно экспериментировать с методами сбора данных и улучшения качества, которые описаны в других главах учебника. Однако при наличии соответствующих мощностей можно улучшать качество, изменяя архитектуру обработки текста. В частности, модели на основе трансформеров (например, BERT) улучшают качество. Это же касается и косинуса, то есть соединительной части. Вполне можно вместо него использовать полносвязную сеть или даже трансформерную архитектуру.
Трансформеры, которые по-отдельности обрабатывают сущности запроса и документа, в Яндексе названы split-моделями и более подробно описаны в том же блоге на Хабре.
Метафичи
В предыдущем пункте мы уже ввели фактор для модели, который сам является значением модели. Мы улучшили качество с помощью стекинга DSSM и итоговой модели. Аналогичным образом можно использовать предсказания моделей, обученных на разные таргеты и разными способами: их можно добавить к другим фичам для итоговой модели.
К сожалению, если факторов-моделей (метафичей) много, такая модель не будет удовлетворять требованиям по времени работы. В этом случае можно прибегнуть к дистилляции знаний большой модели в более компактную.
Фичи, зависящие от времени
Известно, что модель машинного обучения работает хорошо (а точнее, ожидаемо) только в случае, когда при её применении распределения данных и факторов похожи на те, которые использовались при обучении. Но в продакшн-системах постоянное выполнение этого свойства невозможно обеспечить.
Поэтому главный совет: настраивайте мониторинги качества ваших ML-систем для того, чтобы не пропускать моменты поломки. Качество может снизиться как из-за изменений в логике других сервисов, на которые вы полагаетесь при вычислении факторов, так и из-за появления новых трендов. Например, это происходит при появлении новых тем, о которых раньше не было запросов. Показательный случай — пандемия вируса COVID-19, который стал резко появляться среди запросов пользователей.
Но бывают факторы, которые зависят от времени сами по себе. Так, для ранжирования новых документов может быть полезно знать возраст документа. Со временем распределение этого фактора сдвигается вправо, поскольку многие старые документы не удаляются из базы. Получается, фактор старого документа меняется, а релевантность нет. Появление фичей вне ожидаемых значений может привести к непредсказуемому поведению модели. Так что их нужно применять с осторожностью, лучше в тех моделях, которые можно быстро обучить и обновить в продакшне. Ещё лучшим решением будет преобразовать или отнормировать фичи таким образом, чтобы их распределение не менялось так кардинально. Наш фактор с возрастом документа можно преобразовать в индикатор того, что возраст документа меньше одного дня. Тогда только один раз за историю документа этот фактор будет изменён, при этом распределение этого фактора в документах изо дня в день будет похожим.
Многостадийное ранжирование
Представьте, что вы смогли обучить сложную модель, применив все описанные выше подходы: добавили метафичи, которые сами по себе являются формулами, обучили DSSM, BERT, или даже более тяжёлую нейросеть.
Наконец, вам пришёл запрос от пользователя, и вы намерены отсортировать все документы в базе по оценке релевантности, которую даёт ваша модель. Если вы ранжируете 1000, 10000 или даже 100000 документов, это ещё может получиться, и пользователь дождётся ответа. Но что делать, если в вашей базе миллионы, а то и миллиарды документов?
Конечно же вам на помощь могут прийти распределённые системы, и разбив документы по разным инстансам сервиса, который рассчитывает прогноз, вы ускорите получение ответа. Но даже с учётом распределённых вычислений быстро вычислить BERT миллиард раз будет либо очень дорого, либо очень долго. Поэтому применяется подход многостадийного ранжирования.
Тяжёлые модели применяются не сразу. Сначала можно ограничиться применением самых простых оценок релевантности. Как пример, можно просто взять TF-IDF или BM25. Простой моделью отсекаются самые нерелевантные документы, а прошедшие дальше уже сортируются с помощью более ресурсоёмкой и продвинутой модели.
В зависимости от количества документов в базе вы можете соединить столько уровней, сколько нужно, для получения приемлемого времени ответа. Конечно, количество параметров такой системы возрастает в несколько раз, но это делает возможным быстрое взаимодействие с пользователем.
Готовые решения
Если вы разрабатываете продукт, для которого требуется поиск по текстовым документам, для начала вы можете воспользоваться готовыми решениями.
Одним из самых популярных сервисов для поиска является Sphinx. Этот сервис позволяет индексировать текстовые документы и сохранять их в базу данных (как SQL, так и NoSQL). Через специальный SQL-подобный язык запросов он позволяет получать списки релевантных документов и сопутствующие им данные. Таким образом можно доставать только документы, подходящие по заданным фильтрам, отсортированные по релевантности. Это может быть полезно, например, для реализации поиска по интернет-магазину.
Более того, получив некоторый топ выдачи, вы можете переранжировать его, сразу используя сложную модель или учитывая другие потребности ваших пользователей.
Другие альтернативы для текстового поиска можно посмотреть в статье.