Post content
Со мной недавно поделились тредом в Twitter, где парень рассказывает про эксперименты с подходом ColBERT со всякими дополнительными трюками, которые помогли улучшить качество. Стало интересно разобрать основные моменты, так как это в данный момент актуально к моим текущим задачам. Давайте напомню, что такое ColBERT в контексте задачи Retrieval. В обычном сценарии мы прогоняем все наши документы через эмбеддер и строим по ним индекс (получая таким образом отображение document ↔ embedding). Далее для любого запроса мы можем посчитать его эмбеддинг и найти k ближайших соседей как кандидатов на выдачу. ColBERT предлагает здесь уйти от представления “1 вектор на 1 документ”, вместо этого у нас будет n эмбеддингов на документ и k эмбеддингов на запрос. На картинке можно увидеть, как получается итоговый скор для пары запрос-документ. Такое расщепление помогает более детально посмотреть на взаимодействие токенов запроса с токенами документа. В пару предложений тяжело запихнуть описание всего подхода, поэтому посмотрите также оригинальную статью, она написана понятным языком. Из описанных приемов автора мне понравились следующие: 1. Прунинг индекса. Обрабатывая каждый токен по отдельности, мы получаем а) большой индекс б) много ненужных в нем элементов, которые скорее всего будут бесполезны при поиске. Статья 2. Поиск не по всем токенам из запроса, а только по некоторым из них. Своего рода тот же прунинг, но уже для запросов. Статья 3. Дополнительно использовать PRF (pseudo-relevance feedback), то есть делать ретривал в два этапа: на первом извлекать документы для формирования дополнительных эмбеддингов запроса (что-то по типу query expansion), а на втором уже искать финальные документы для выдачи. Схема изображена на картинке. Статья Если использовали что-то из этого, расскажите, интересно послушать, что взлетело, а что нет. По моим экспериментам не могу сказать, что ColBERT вообще стат. значимо докидывал по сравнению с хорошо настроенными bi-encoder трансформерами, но это в задаче поиска товаров.