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

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

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

Наш конвейер машинного обучения

У нас есть очень простой обзор, который показывает ключевые части конвейера машинного обучения.

  1. Обработка данных. Это следует запускать часто для потоковой передачи и обработки данных о посещениях пользователей и сохранения их в качестве данных рейтинга.
  2. Машинное обучение. Его следует запускать периодически (например, раз в неделю) для (повторного) обучения данных.
  3. Приложение/презентация.Внешнее приложение будет использовать KNN, сгенерированный из последнего обученного алгоритма.

Генерировать неявные рейтинги

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

  • Время, проведенное на странице продукта.Больше время, проведенное на странице, свидетельствует о том, что пользователь заинтересован в продукте, прочитав информацию о продукте и т. д.
  • Второстепенные действия.Некоторые действия, такие как добавление продукта в список желаний для покупок или просмотр продукта, когда его нет в наличии, также могут указывать на уровень интереса пользователей.
  • Основные действия. Такие действия, как добавление товара в корзину или покупка товара (оформление заказа), могут быть очень хорошими индикаторами уровня интереса пользователя к продукту.

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

Например, очень простое правило может быть (для шкалы оценок от 1 до 5):

Если пользователь проводит на странице товара более 2 минут, мы даем ему оценку 5; от 1 до 2 минут - рейтинг 4, менее 1 минуты - рейтинг 3 (для обозначения среднего/нейтрального рейтинга).

Затраченное время должно основываться на общем распределении времени, проведенного на страницах продукта (например, 2 минуты — это 2 стандартных отклонения от среднего и т. д.).

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

Для технической реализации анонимные данные о поведении пользователей можно получить из аналитического программного обеспечения, такого как Google Analytics, Adobe Analytics, Matomo и т. д.

Рейтинги процесса

В зависимости от объема трафика, который получает ваш интернет-магазин, вы можете отслеживать трафик посетителей и генерировать рейтинги в режиме реального времени или получать их периодически (например, каждые 30 минут).

Если ваш магазин сезонный (например, праздничные товары, весенняя коллекция и т. д.), вы также можете периодически удалять рейтинговые данные. Это потенциально может сделать рекомендацию более динамичной и отразить сезонность поведения пользователя.

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

Обучение алгоритмам и данным

На этом этапе у нас должна быть рейтинговая таблица, состоящая как минимум из идентификатора пользователя, идентификатора продукта, рейтинга (1–5).

Иногда полезно иметь дополнительные столбцы данных (например, понятные для человека названия продуктов), чтобы быстро экспериментировать и выполнять проверки правильности рекомендаций.

Для обучения данных мы можем использовать Python Surprise library. Это очень простая и удобная библиотека со множеством алгоритмов совместной фильтрации.

Давайте рассмотрим простой пример:

from surprise import Dataset, Reader, KNNWithMeans
reader = Reader(line_format='user item rating', sep=',', rating_scale=(1,5))
data = Dataset.load_from_file('/path/to/ratings.csv', reader=reader)
trainingSet = data.build_full_trainset()
sim_options = {
  "name": "cosine", 
  "min_support": 3,
  "user_based": False
}
algo = KNNWithMeans(sim_options = args)
algo.fit(trainingSet)

Здесь мы по существу делаем следующее:

  1. Загрузите наши рейтинговые данные из CSV-файла в обучающий набор. В производственной среде вы также можете загрузить данные из фрейма данных Pandas.
  2. Мы создаем наш TrainingSet, используя весь набор данных. Нам не нужно разбивать набор данных на обучение/тест, поскольку нам не нужно запускать прогнозирование и измерять точность нашего алгоритма.
  3. Указываем список разумных вариантов для нашего алгоритма.
    Например, используйте косинусное расстояние (вместо msd), чтобы измерить сходство между продуктами.
    min_support — это количество общих элементов между пользователями, прежде чем мы будем рассматривать их на предмет сходства.
    user_based имеет значение False, чтобы указать, что мы будем использовать совместную фильтрацию на основе элементов.

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

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

Здесь мы используем алгоритм KNNwithMeans. Это основанный на памяти алгоритм совместной фильтрации, который работает быстро. SVD и другие алгоритмы на основе моделей более точны, если вы выполняете прогнозы.

Найдите KNN и представьте рекомендации

После обучения данных алгоритм рассчитает матрицу сходства. Это будет матрица формы (n,n), где n = количество элементов (продуктов) в тренировочном наборе. Он будет содержать косинусное расстояние между всеми продуктами и всеми другими продуктами. (Матрица также должна иметь диагональ из нулей, так как расстояние произведения до самого себя будет равно 0)

В некоторых реализациях диагональ матрицы подобия будет равна единице (1), при этом используется коэффициент подобия (1 — косинусное расстояние).

Нашей целью будет «данный продукт, найти его KNN (K ближайших соседей)». Другой способ сказать это: дать мне продукты, которые наиболее похожи на данный продукт (на основе оценок пользователей). .

k = 4 # We are looking for the top 4 similar products
sim_list = [] 
knn = [] # contain the product ids of the k similar products 
product_id = '123456'
innerId = trainingSet.to_inner_iid(product_id)
# The exclusion id sequence, if the KNN is 0 to 4 means we are not getting a valid KNN
ex_id_seq = {0:0,1:1,2:2,3:3,4:4}
if innerId in ex_id_seq.keys():
  del ex_id_seq[innerId]
# Finding the k nearest neighbors using the similarity matrix
neighbors = algo.get_neighbors(innerId, k)
for iid in neighbors:
  sim_list.append(iid)
# Check to see if the sims list contains the exclusion id sequence
check_default_ids = set(ex_id_seq.keys()).issubset(sim_list)
if check_default_ids:
  # Find the position (index) within the sim_list
  first_ex_id = list(ex_id_seq.values())[0]
  sim_list = sim_list[:sim_list.index(first_ex_id)]
for id in sim_list:
  knn.append(trainingSet.to_raw_iid(id))

Есть несколько особенностей поиска KNN:

Алгоритм сохраняет user_id и product_id как innerID, поэтому вам всегда нужно выполнять преобразование, например

trainingSet.to_inner_iid(product_id)

Когда алгоритму не удается найти k ближайших соседей для продукта, он всегда возвращает первые k элементов из набора данных (от 0 до k-1). Мы ищем эту последовательность и не включаем ее в наш список рекомендаций.

Наконец, пример рекомендации с использованием этого алгоритма выглядит следующим образом:

Другие наблюдения

Алгоритм сильно зависит от наличия достаточного количества трафика в интернет-магазине, поэтому он не будет эффективным, если интернет-магазин получает мало трафика (например, новые магазины).

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

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

Следующие шаги

Подход, который мы применяли до сих пор, основывался на сценарии рекомендации "данный продукт, покажите мне N связанных продуктов на основе неявных оценок пользователя".

Мы можем лучше использовать преимущества алгоритмов совместной фильтрации, делая прогнозы лучших рекомендаций продукта для данного пользователя. Это означает: «для данного пользователя покажите мне N лучших продуктов, рекомендованных этому пользователю».

Для этого нам потребуется:

  • Собирайте и создавайте живые рейтинги для пользователя, который в данный момент просматривает интернет-магазин.
  • Найдите наиболее похожего пользователя на основе неявных оценок текущего пользователя из ранее обученного алгоритма.
  • Сделайте лучший прогноз N для этого «наиболее похожего пользователя» и представьте его текущему пользователю.

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