Как мы используем встраивания на основе взаимодействия для улучшения поиска и рекомендаций на Faire

Введение

Оптовая торговая площадка Faire объединяет более 600 000 независимых ритейлеров с более чем 85 000 брендов по всему миру. Наша команда Discovery постоянно стремится улучшить взаимодействие с платформой для нашего сообщества клиентов по всему миру, включая разработку и внедрение моделей и алгоритмов, которые помогают персонализировать рейтинг продуктов на странице результатов поиска, навигацию по категориям, страницу бренда и карусели рекомендаций. Чтобы узнать больше, ознакомьтесь с прошлыми статьями в блоге The Craft о Создание новой инфраструктуры ранжирования на рынке Faire и Рейтинг в реальном времени на Faire: магазин функций.

В то время как в предыдущих статьях основное внимание уделялось основам нашей инфраструктуры ранжирования, в этом посте мы расскажем больше о наших усилиях по внедрению. Мы видели, как более широкая отрасль в последнее десятилетие вкладывала значительные средства в эту область, где числовое векторное представление различных объектов рынка изучается с помощью моделей машинного обучения. В Faire мы также используем широкий спектр вложений, чтобы помочь информировать Поиск и Рекомендации, быстро найти наиболее релевантные продукты, которые ищут покупатели, или вдохновить наших розничных продавцов, предлагая популярные бренды и продукты, которые они еще не пробовали.

В частности, мы объясним, как мы изучаем внедрение розничных продавцов, продуктов и брендов, мы углубимся в создание обучающих данных, архитектуру модели и функцию потерь, которая обеспечивает наилучший баланс между производительностью и временем обучения. Вы также узнаете больше о том, как мы обслуживаем встраивания в рабочей среде, которые используются для различных поверхностей поиска и рекомендаций, чтобы обеспечить значимое влияние на бизнес.

Машина факторизации

В прошлом мы использовали LightFM для изучения встраивания ритейлера, продукта и бренда. LightFM — это пакет, который реализует метод факторизации, который использует как взаимодействие розничного продавца с продуктом/брендом, так и побочные функции для создания вложений розничного продавца и продукта, чей точечный продукт (плюс условия смещения) аппроксимирует вероятность взаимодействия между ними.

LightFM хорошо служил нам в первые дни. Однако природа LightFM как «черный ящик» затрудняет развитие архитектуры модели для соответствия постоянно растущим размерам и сложности бизнес-потребностей Faire. В результате мы решили перейти от LightFM к стеку PyTorch, который дает нам дополнительную прозрачность, гибкость и масштабируемость для размещения гораздо большего каталога продуктов и большего количества архитектур моделей для изучения. Ниже мы объясним, как Faire создала собственный стек PyTorch для встраивания обучения, основываясь на исторических взаимодействиях с продуктами розничных продавцов.

Тренировочные данные

Чтобы изучить встраивание продуктов розничного продавца, мы в основном генерируем обучающие данные, используя наши сигналы о добавлении в корзину, оформлении заказа и посещении страницы продукта в виде положительных образцов в следующей табличной форме данных:

Здесь может показаться, что мы генерировали только положительные метки/сигналы в наших обучающих данных. Как насчет отрицательных образцов? Для этого мы могли бы выполнять пакетную перетасовку во время процесса обучения, чтобы генерировать отрицательные образцы на лету. Преимущество этого заключается в значительном упрощении процесса генерации обучающих данных и сокращении времени работы обучающего конвейера, поскольку мы можем делать это в памяти (в качестве следующих шагов мы рассмотрим более сложные методы выборки).

В разделе о функции потерь ниже мы подробно объясним, как мы выполняем пакетную случайную отрицательную выборку.

Архитектура модели

Мы реализовали обучение нашей модели в PyTorch. В частности, мы использовали типичную архитектуру модели с двумя башнями (по мотивам работы с Youtube), где у нас есть и башня ритейлера, и башня продукта для встраивания генерации и расчета косинусного сходства с аппроксимацией предпочтения продукта ритейлера в конечном результате. слой.

Ниже приведена упрощенная архитектура модели. Мы подробно объясним логику встраивания продавца/продукта и разреженных функций в PyTorch.

Инициализация и поиск внедрения продавцов и продуктов

Мы используем модуль встраивания PyTorch для инициализации и поиска встраиваемых продавцов и продуктов. Ниже приведен код, вырезанный для инициализации. По сути, справочная таблица для внедрения розничного продавца представляет собой матрицу формы [n_retailer, embedding_length], аналогично, справочная таблица для внедрения продукта имеет форму [n_product, embedding_length]

self.retailer_embeddings = nn.Embedding(self.n_retailer, embedding_length).to(
    self.device
)
self.product_embeddings = nn.Embedding(self.n_product, embedding_length).to(
    self.device
)

Разреженные функции

В дополнение к самим встраиваниям розничного продавца и продукта, другие функции также могут помочь модели изучить скрытые представления, такие как бренд продукта, тип таксономии продукта, страна продукта и т. д.

Чтобы обобщить текущую настройку модуля nn.Embedding для продавца и продукта, мы также применяем инициализацию внедрения для этих так называемых побочных функций. Мы объединяем эти вложения вместе для встраивания конечного продукта. Благодаря этому дизайну мы можем воспользоваться высокооптимизированным модулем nn.Embedding для размещения побочных функций высокой мощности, таких как типы таксономии.

Код для настройки побочных функций с помощью nn.Embedding также довольно прост, и нам нужно знать только сопоставление product<>sparse_feature. Одна деталь здесь заключается в том, что мы используем nn.ModuleDict для регистрации этой карты вложений.

def _initialize_item_sparse_feature_bias_embedding(self):
      sparse_embeddings = dict()
      biases = dict()
      total_emb_dim = 0
      for f in self.item_sparse_features:
          sparse_feature_cardinality = len(self.sparse_feature_idx_mappers[f])
          sparse_embeddings[f] = nn.Embedding(
              sparse_feature_cardinality, self.embedding_length).to(
                  self.device
              )
          biases[f] = nn.Embedding(cardinality, 1).to(self.device)
        # Use ModuleDict to register embeddings to model parameters
      return nn.ModuleDict(sparse_embeddings), nn.ModuleDict(biases)

Функция потери

Потеря взвешенного приблизительного ранжирования попарно (WARP)

Теперь, когда мы знаем, как рассчитать показатель сходства retailer<>product, далее мы объясним, как мы рассчитываем потерю рейтинга при положительной паре вовлеченности retailer<>product.

Интуитивно эта функция потерь пытается изучить встраивание вовлеченного продукта по сравнению с никогда не вовлечённым, чтобы в скрытом пространстве встраивания заинтересованный продукт розничного продавца был ближе, а незаинтересованный продукт розничного продавца был дальше.

Модифицированная потеря WARP

При реализации обучения модели в PyTorch с использованием приведенного выше определения потерь WARP мы понимаем, что алгоритм будет:

  1. случайно попробовать другой продукт, с которым продавец никогда раньше не работал, и
  2. повторять до тех пор, пока сходство отрицательных образцов не станет выше

Это приведет к тому, что обучение станет немасштабируемым и займет много времени:

  1. Если мы реализуем отрицательную выборку на этапе генерации обучающих данных, это значительно увеличит время и размер генерации обучающих данных.
  2. Если мы реализуем это во время обучения модели, мы также не можем гарантировать условие никогда не привлекались раньше, так как нам нужно будет знать все исторические взаимодействия с продуктом розничного продавца, которые не могут уместиться в памяти.
  3. Наконец, итеративный процесс также может увеличить время обучения.

Для решения этих проблем мы внедрили следующую модификацию. Благодаря автономной итерации мы поняли, что перетасовка в пакете дает как хорошее приближение к точной потере, так и разумное время обучения. Ниже приведен псевдокод для иллюстрации пакетной случайной перестановки:

for i in range(0, K):
    shuffled_product_ids = batch[torch.randperm(batch.product_ids)]
  negative_product_embeddings = self._gen_item_embeddings(shuffled_product_ids)
    negative_prediction = user_embeddings * negative_product_embeddings   
    predictions.append(negative_prediction.unsqueeze(1))

Вот пример для размера партии = 10 и времени перемешивания K = 3.

Мы видим, что после перетасовки перетасованный продукт, скорее всего, является продуктом, с которым розничные продавцы никогда раньше не взаимодействовали. На самом деле у нас может возникнуть ситуация, когда продавец уже занимается перетасовкой товаров. Путем автономной итерации и анализа мы убедились, что случайная перестановка создает высококачественные вложения даже при потенциальных ложноотрицательных выборках. Мы перетасовали три раза, что означает, что мы ограничим количество шагов итерации до 3. Теперь у нас есть измененная взвешенная приблизительная потеря ранжирования следующим образом:

Обучение моделей и обслуживание

Теперь, когда мы рассмотрели создание обучающих данных, архитектуру модели и функцию потерь, у нас есть все ингредиенты для окончательного обучения модели.

  1. Мы создадим сценарий обучения в виде образа докера и будем запускать его в Airflow через день.
  2. Мы будем хранить подготовленные розничные продавцы, продукты и внедренные бренды в нашем специализированном магазине и сможем искать их в Интернете.
  3. Для всех активных брендов мы будем хранить наиболее похожие бренды, рассчитанные на основе сходства внедрения бренда. Функциональность topK исходит от встроенного автономного индексатора, такого как Annoy и Faiss.

Встраивание приложений

В Faire есть два основных типа приложений для встраивания:

  1. Генерация кандидатов с NearestSearch (NN)
  2. Внедрение оценок сходства на основе поиска и ранжирования.

Мы привели четыре примера, которые охватывают оба типа приложений на наших поверхностях обнаружения. Ниже приведена простая диаграмма, которая помогает продемонстрировать основные поверхности открытий на Faire:

Навигация по категориям и поиск

На Faire страница категории управляется персонализацией. Добавление сходства продуктов розничных продавцов в качестве сигнала персонализации на этапе поиска поможет розничным продавцам найти наиболее востребованные продукты и, следовательно, повысить GMV.

В то время как встраивание на основе взаимодействия может быть мощным рычагом в поиске, вычисление встраивания косинусных сходств чрезвычайно ресурсоемко, особенно когда на Faire продаются миллионы продуктов. В идеале методы поиска на основе приближенного ближайшего соседа (ANN) являются оптимальным вариантом для поддержки полного сканирования продуктов. В нашем случае текущая инфраструктура поиска еще не поддерживает полный поиск ANN. Мы нашли обходной путь, используя встроенную функцию повторной оценки Elasticsearch, которая принимает сценарий повторной оценки и выполняет сценарий для лучших кандидатов с точки зрения оценки поиска при первом проходе.

Еще одним ключевым параметром в этом эксперименте является размер окна пересчета. Мы тщательно выбирали размер повторной оценки, чтобы сбалансировать компромисс между качеством результатов поиска и задержкой. После сравнительного анализа задержки мы переоценили 100 000 лучших кандидатов для каждого запроса, что только добавило 20 мс задержки к этапу извлечения, но все еще было достаточно большим, чтобы встраивания могли показать его мощь.

Мы запустили эксперимент с контрольной группой, используя только показатель качества продукта, и лечение с использованием сходства продуктов розничного продавца для повторной оценки. Блок-схема ниже иллюстрирует высокоуровневый процесс поиска:

Мы также экспериментируем с прямым добавлением сходства продуктов розничных продавцов в наш поисковый рейтинг. В частности, в нашем автономном анализе мы заметили, что эта встроенная функция подобия является самой важной новой функцией, которую мы внедрили с большим отрывом!

Страница бренда

Еще один способ, которым мы используем вложения, — это наш вариант использования рекомендаций. Когда продавец посещает страницу определенного бренда, мы показываем и рекомендуем похожие бренды, чтобы помочь ему найти дополнительные продукты.

В этом случае мы находим лучшие бренды, похожие на текущий бренд, используя показатель сходства брендов, рассчитанный на основе внедрений брендов, и сохраняем лучших кандидатов в DynamoDB с идентификатором бренда в качестве ключа. Затем, во время онлайн-обслуживания, мы извлекаем аналогичные бренды с учетом текущего бренда через DynamoDB и ранжируем в реальном времени для окончательного ранжирования.

Домашняя страница

Мы также используем встраивания на нашей домашней странице, где для каждой отдельной карусели мы ранжируем продукты и бренды на основе их оценки сходства продукта/бренда розничного продавца. Ниже мы показываем домашнюю страницу продавца продуктов питания и напитков, полностью персонализированную для них.

Заключение

В этой статье мы рассмотрели создание обучающих данных, выбор функции потерь и показали, как мы строим модель с двумя башнями для изучения встраивания розничных продавцов и продуктов на основе исторических взаимодействий розничных продавцов с продуктами. Мы также рассмотрели несколько приложений для встраивания на наших основных платформах обнаружения, которые в конечном итоге помогают нашим клиентам развивать свой бизнес. К ним относятся помощь розничным продавцам в поиске более персонализированных продуктов с помощью ранжирования в поиске и навигации по категориям, упрощение поиска новых брендов, которые могут их заинтересовать, и персонализация домашних страниц на основе профилей розничных продавцов. В целом, мы продемонстрировали, что встраивания являются важнейшими компонентами современных систем поиска и рекомендаций, а с существующей экосистемой глубокого обучения настроить ее для собственного варианта использования еще никогда не было так просто!

Выкрикивать

Спасибо этой группе талантливых специалистов по данным и инженеров за эту замечательную работу — Сэм Кенни, Цинью Ван, Сяомэн Ху, Вэй Цзян, и это лишь некоторые из них.

Мы только начали поверхностно внедрять обучение и приложения. Команда также внедрила встроенные продукты для запроса и взаимодействия с продуктом, а многомодальное встраивание — для описания продукта, изображения продукта и т. д. Следите за будущими сообщениями в блоге, чтобы узнать больше о том, как мы используем данные и машинное обучение для мощность платформы Faire!

Если вы хотите присоединиться к команде данных мирового уровня, работающей над инновационными задачами, чтобы помочь предпринимателям во всем мире осуществить свои мечты — присоединяйтесь к нам! www.faire.com/careers