«Клиенты, которые купили это, также купили…» Мы часто сталкиваемся с персональными рекомендациями во время покупок на Amazon, прослушивания музыки на Spotify и просмотра сериалов на Netflix, и это лишь некоторые из них. Они настолько широко распространены, что многие из нас взаимодействуют с ними, даже не осознавая этого. Все эти веб-сайты пытаются оценить наши вкусы, чтобы обеспечить постоянное взаимодействие. Эти компании используют наши модели покупок/слушания/просмотра, чтобы предсказать, что нам может понравиться в будущем. В некотором смысле рекомендательные системы беспроигрышны как для пользователей, так и для бизнеса. Для пользователей они предлагают лучший опыт и взаимодействие, а для бизнеса они помогают увеличить доходы.

Совместная фильтрация

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

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

Совместную фильтрацию можно разделить на:

  • На основе пользователей. В зависимости от оценок, которые пользователи поставили одним и тем же элементам, мы пытаемся определить пользователей со схожими вкусами/предпочтениями с пользователем А, используя косинусное сходство. Кроме того, мы используем взвешенную сумму оценок, предоставленных ближайшими соседями (то есть пользователями-единомышленниками в качестве A) для элемента X, и вычисляем предварительную оценку, которую пользователь A может предоставить этот пункт.
  • На основе элементов. В отличие от измерения сходства между пользователями подход на основе элементов направлен на поиск похожих элементов/продуктов. Оценка пользователя по элементу X затем прогнозируется путем взвешивания суммы оценок, предоставленных пользователем ближайшим соседям (в данном случае - другим элементам, аналогичным элементу X). ). Предметно-ориентированный подход — успешная методика, которую широко используют различные компании.

Набор данных кинообъектива

В этой статье мы рассмотрим два подхода совместной фильтрации и используем набор данных Movie Lens для создания базовой системы рекомендаций на Python. Этот набор данных описывает рейтинги, составленные по 5-звездочной шкале с шагом в ползвезды. Он содержит 100 836 оценок 9 742 фильмов, созданных 610 пользователями. Пользователи были выбраны случайным образом для включения. Все выбранные пользователи оценили не менее 20 фильмов. Демографическая информация не включена. Каждый пользователь представлен идентификатором, и никакой другой информации не предоставляется.

Косинус сходства

Прежде чем мы перейдем к алгоритму, давайте сначала разберемся с косинусным сходством.

Косинусное сходство количественно определяет сходство между двумя ненулевыми векторами и находится в диапазоне от 0 до 1. Это косинус угла между векторами. Математически это определяется следующим образом:

Построение модели в Python

Чтобы было понятнее, начнем с алгоритма. Эти шаги являются общими для подходов на основе пользователей и элементов.

  • Импорт соответствующих библиотек Python. На первом этапе мы импортируем библиотеки pandas, numpy для обработки данных. Мы также импортируем os для выборки/изменения рабочего каталога. train_test_split, StratifiedKFold и cosine_similarilty импортируются для разделения набора данных, выполнения перекрестной проверки и вычисления показателей сходства соответственно. Наконец, для оценки нашей модели мы также импортируем mean_absolute_error.
  • Загрузка и чтение данных. Следующим шагом является загрузка набора данных Movie Lens и чтение данных оценок. Кроме того, мы можем выполнить некоторую EDA и предварительную обработку этих данных.
# reading the ratings data
ratings=pd.read_csv('ratings.csv')

# unique ratings
print('Unique ratings: ', ratings['rating'].unique(), '\n')

# number of ratings
print('Number of ratings: ', len(ratings), '\n')

# number of unique users
print('Number of unique users: ', len(ratings['userId'].unique()), '\n')

# number of unique movies
print('Number of unique movies: ', len(ratings['movieId'].unique()), '\n')

# removing the redundant column timestamp
df=ratings.iloc[:,:-1]
df

Output

Unique ratings:  [4.  5.  3.  2.  1.  4.5 3.5 2.5 0.5 1.5] 

Number of ratings:  100836 

Number of unique users:  610 

Number of unique movies:  9724 

  • Внедрение стратифицированной выборки при перекрестной проверке. Теперь идея состоит в том, чтобы разделить наш набор данных на обучающую и тестовую подмножества. Мы позволим модели обучаться на обучающем наборе, а затем измерим ее производительность на тестовом наборе. Чтобы оценить, как результаты обобщаются на независимый набор данных, и предотвратить переоснащение, мы выполняем перекрестную проверку. При перекрестной проверке набор данных делится на k разбиений. Мы используем сплиты k-1 для обучения, а оставшийся сплит используется для тестирования. Модель проходит через весь набор данных k раз, и каждый раз для тестирования используется другое разделение. Таким образом, мы используем все точки данных как для обучения, так и для тестирования. Стратифицированные k сгибов делают перекрестную проверку еще на один шаг вперед. Это гарантирует, что распределение классов в наборе данных сохраняется в наборах для обучения и тестирования.
Output

StratifiedKFold(n_splits=5, random_state=None, shuffle=False)

Fold:  1
TRAIN: [    47     48     49 ... 100833 100834 100835]  having:  80668
TEST: [    0     1     2 ... 99792 99793 99794]  having:  20168
------------------------------------

Fold:  2
TRAIN: [     0      1      2 ... 100833 100834 100835]  having:  80669
TEST: [    47     48     49 ... 100052 100053 100054]  having:  20167
------------------------------------

Fold:  3
TRAIN: [     0      1      2 ... 100833 100834 100835]  having:  80669
TEST: [    94     95     96 ... 100312 100313 100314]  having:  20167
------------------------------------

Fold:  4
TRAIN: [     0      1      2 ... 100833 100834 100835]  having:  80669
TEST: [   140    141    142 ... 100572 100573 100574]  having:  20167
------------------------------------

Fold:  5
TRAIN: [     0      1      2 ... 100572 100573 100574]  having:  80669
TEST: [   186    187    188 ... 100833 100834 100835]  having:  20167
  • Оценки и матрица сходства. Мы делаем сводку из обучающего набора данных, взяв userId в строках и movieId в столбцах и рейтинг как значения. В результате получается разреженная Матрица оценок, в которой NaN можно заменить нулями.

  1. Матрица сходства между пользователями. Далее мы измеряем сходство между пользователями. Корреляция Пирсона и косинусное сходство - два широко используемых метода. В нашем случае мы будем использовать косинусное сходство для вычисления оценок сходства между пользователями. Поскольку косинусное подобие не принимает пропущенных значений, мы должны приписать им нули перед вычислением подобия.

2. Матрица сходства между элементами. Точно так же мы можем вычислить показатели сходства между элементами. Мы транспонируем нашу матрицу оценок, а затем измеряем косинусное сходство между элементами.

Совместная фильтрация на основе пользователей

  • Функция для прогнозирования оценок.Затем мы создаем функцию, которая прогнозирует оценки пользователя A по элементу X, используя взвешенные сумма оценок ближайших соседей этого пользователя. Другими словами, мы используем оценки других пользователей-единомышленников, чтобы предлагать новые элементы для пользователя А. Чтобы найти ближайших соседей, мы можем использовать различные методы. Во-первых, мы можем установить порог сходства, скажем, similarity_threshold, и отфильтровать всех пользователей, у которых показатель сходства выше этого similarity_threshold. Еще один метод поиска ближайших соседей – это просто выбор первых n пользователей с наибольшим косинусным сходством. Давайте воспользуемся первым подходом для пользовательской фильтрации, а второй — для совместной фильтрации на основе элементов.
  1. Приведенная выше функция calculate_ratings принимает три параметра: id_movie, id_user, similarity_threshold.
  2. На основе порога, переданного в функцию, она находит ближайших соседей id_user.
  3. Затем удаляются пользователи, не оценившие id_movie.
  4. С оставшимися ближайшими соседями он вычисляет сумму рейтингов, взвешенных по их показателям сходства.
  5. Если id_movie отсутствует в матрице рейтингов, он просто возвращает нейтральный рейтинг 2,5.
  • Функция для оценки тестовых данных и возврата MAE: eval_test_data сравнивает прогнозируемые рейтинги с фактическими рейтингами тестовых данных и возвращает среднюю абсолютную ошибку.

Результат. Наконец, мы реализуем все описанные до сих пор шаги для совместной фильтрации на основе пользователей и получаем среднюю абсолютную ошибку на тестовых данных для каждой складки. При вызове функции eval_test_data мы устанавливаем 0,4 в качестве порога. Это означает, что алгоритм будет фильтровать в качестве ближайших соседей только тех пользователей, у которых сходство между пользователями больше или равно этому порогу. Кроме того, мы вычисляем среднее значение MAE для всех пяти сгибов и смотрим, насколько хорошо работает наш алгоритм.

Совместная фильтрация на основе элементов

  • Функция прогнозирования оценок.Подобно подходу на основе пользователей, мы можем создать функцию calculate_ratings, которая прогнозирует оценку элемента X пользователем A. > используя взвешенную сумму рейтингов ближайших соседей этого элемента. Другими словами, мы используем оценки других похожих элементов, чтобы предложить новые элементы для пользователя А.В этом случае методология выбора ближайших соседей заключается в фильтрации первых n элементов с наивысшим показателем сходства.
  1. Приведенная выше функция calculate_ratings снова принимает три параметра: id_movie, id_user, top_k_similar.
  2. На основе порога, переданного в функцию, она находит top_k_similar ближайших соседей id_movie.
  3. Затем удаляются фильмы/объекты, которые не были оценены id_user.
  4. С оставшимися ближайшими соседями он вычисляет сумму рейтингов, взвешенных по их показателям сходства.
  5. Если id_user отсутствует в матрице рейтингов, он просто возвращает нейтральный рейтинг 2,5.

Результат:по аналогии с совместной фильтрацией на основе пользователей мы реализуем все шаги, обсуждавшиеся до сих пор для совместной фильтрации на основе элементов, и получаем среднее абсолютное ошибка в тестовых данных для каждой складки. При вызове функции eval_test_data мы устанавливаем пороговое значение 40. Это означает, что алгоритм будет фильтровать только первые 40 элементов как ближайших соседей, имеющих наибольшее косинусное сходство. Опять же, мы вычисляем среднее значение MAE для всех пяти сгибов и смотрим, насколько хорошо работает наш алгоритм.

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