Внедрение демографической фильтрации, контентной фильтрации и совместной фильтрации на практике

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

В этом проекте будут реализованы три типа рекомендательных систем:

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

Поняв механизм системы рекомендаций, давайте начнем наш первый проект системы рекомендаций с использованием набора данных фильмов TMDB, который можно загрузить через Kaggle здесь. Этот набор данных содержит 2 набора файлов: файл Credits и файл фильмов. Файл Credits имеет размер 38 МБ и содержит 4 функции, а именно: идентификатор фильмов, названия, имена актеров (участники на экране) и имена членов съемочной группы (участники за кулисами). С другой стороны, при размере 5,4 МБ файл фильмов содержит больше функций, а именно: бюджет фильма, жанр, домашнюю страницу, идентификатор, ключевые слова, язык оригинала, исходное название, производственные компании, страны производства, дату выпуска, доход, время выполнения (в минутах), статус (выпущено или по слухам), слоган, заголовок, среднее количество голосов и количество голосов.

Как обычно, во-первых, нам нужно импортировать несколько стартовых библиотек следующим образом:

import numpy as np
import pandas as pd

Если вы используете Google Colab, не забудьте загрузить файлы Movies and Credits в Colab следующим образом:

from google.colab import files
uploaded = files.upload()

А затем назначьте эти файлы переменным с помощью функции чтения Pandas и прочтите их размеры:

credits = pd.read_csv('tmdb_5000_credits.csv')
movies = pd.read_csv('tmdb_5000_movies.csv')
print(credits.shape)
print(movies.shape)

Как мы видим ниже, оба файла содержат 4803 данных с 4 функциями для файла Credits и 20 функциями для файла фильмов.

Поскольку есть два файла, мы должны объединить эти файлы на основе их идентификаторов фильмов. Но перед объединением изменим столбец «Идентификатор фильмов» в титрах на «Идентификатор», чтобы они имели идентичную функцию «Идентификатор» при объединении, а затем проверим размер нового объединенного файла.

credits.columns = ['id','tittle','cast','crew']
movies= movies.merge(credits,on='id')
print(movies.shape)

Теперь наш новый объединенный файл содержит 23 функции, как показано ниже:

Демографическая фильтрация

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

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

Где:

  • W = взвешенный рейтинг
  • v = количество голосов за фильм
  • m = минимальное количество голосов, необходимых для рассмотрения
  • R = средний номер рейтинга фильма
  • C = средний голос из общих данных

Следовательно, нам необходимо определить каждый из этих элементов, чтобы получить W. Количество голосов (v) и среднее количество голосов (R) уже указаны в наборе данных, поэтому нам не нужно производить дальнейшие вычисления для этих переменных. . Затем нам нужно найти C - среднее значение общего числа голосов, которое можно определить с помощью следующей функции:

C= movies['vote_average'].mean()

Если мы попытаемся распечатать значение C, мы получим 6.092 .. следующим образом:

Затем нам нужно определить m - количество голосов, необходимое для того, чтобы фильм рассматривался как рекомендация. Мы можем установить его как любое число, однако, допустим, в нашем алгоритме мы установим его как 85-й процентиль в качестве порогового значения, что означает, что фильм должен иметь больше голосов, чем 85% от общего числа фильмов. Давайте разберемся:

m= movies['vote_count'].quantile(0.85)

Как мы видим ниже, для того, чтобы фильм попал в рекомендацию, он должен набрать не менее 1301 голоса в своем рейтинге.

Используя значение m, мы можем исключить фильмы с количеством оценок ниже 1301 следующим образом:

demograph_movies = movies.copy().loc[movies['vote_count'] >= m]

Сейчас мы можем увидеть только 721 фильм из 4803, набравших более 1301 голоса.

После того, как мы выяснили все элементы, давайте создадим формулу взвешенного рейтинга IMDB, определив ее функцию, как показано ниже:

def weighted_rating(a, m=m, C=C):
  v = a['vote_count']
  R = a['vote_average']
  return (v/(v+m) * R) + (m/(m+v) * C)

Затем мы можем вставить результаты формулы IMDB в файл демографических рекомендаций, создав новую функцию под названием «оценка».

demograph_movies['score'] = demograph_movies.apply(weighted_rating, axis=1)

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

demograph_movies = demograph_movies.sort_values('score', ascending=False)

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

demograph_movies[['title', 'vote_count', 'vote_average', 'score']].head(10)

Оказалось, что The Shawshank Redemption возглавили чарт, за ним следуют «Бойцовский клуб» и «Криминальное чтиво». Это действительно отличные фильмы, однако эта система рекомендаций применима ко всем, независимо от жанра пользователя или предпочтений других факторов, поэтому она считается далекой от идеальной.

Контентная фильтрация

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

Рекомендация на основе описания фильма

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

movies['overview'].head(10)

Поскольку здесь мы имеем дело с предложениями, разумнее использовать одну из техник NLP (обработка естественного языка), называемую TF-IDF, которая является сокращением от Term Frequency-Inverse Document Frequency. Что делает TF-IDF, он анализирует важность каждого слова, находя TF и ​​IDF, используя следующие формулы:

И тогда TF-IDF можно найти, просто умножив результат TF и ​​IDF, поэтому:

TF-IDF = TF * IDF

Расчет TF-IDF был предоставлен библиотекой Scikit-Learn, которую можно импортировать с помощью следующего кода:

from sklearn.feature_extraction.text import TfidfVectorizer

Перед выполнением TF-IDF нам необходимо выполнить необходимые задачи предварительной обработки NLP, такие как удаление стоп-слов (слов, не имеющих значения, например, «а», «то», «но», «что» , «Или», «как» и «и») путем присвоения новой переменной.

tfidf = TfidfVectorizer(stop_words='english')

И еще нам нужно заменить NaN пустой строкой:

movies['overview'] = movies['overview'].fillna('')

Затем мы можем применить векторизацию TF-IDF к обзору фильмов и проверить его размер:

tfidf_overview = tfidf.fit_transform(movies['overview'])
tfidf_overview.shape

Как мы видим выше, более 20 000 слов используются для описания 4803 фильмов в функции «Обзор».

Поскольку мы рассчитали векторизацию TF-IDF для предложений обзора, теперь мы можем обнаружить сходство между двумя фильмами, которые на самом деле имеют несколько методов, таких как евклидова корреляция, корреляция Пирсона и косинусное сходство. Однако, учитывая простоту, мы будем использовать косинусные сходства, которые можно получить с помощью функции linear_kernel () из библиотеки sklearn.

Во-первых, нам нужно импортировать линейное ядро ​​из sklearn ниже:

from sklearn.metrics.pairwise import linear_kernel

Тогда мы сможем узнать через него косинусное подобие.

cos_sim = linear_kernel(tfidf_overview, tfidf_overview)

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

indices = pd.Series(movies.index, index=movies['title']).drop_duplicates()

Затем мы можем приступить к созданию функции рекомендации фильмов на основе их описаний следующим образом:

def des_recommendations(title, cos_sim=cos_sim):
    idx = indices[title]
    sim_scores = list(enumerate(cos_sim[idx]))
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
    sim_scores = sim_scores[1:16]
    movie_indices = [i[0] for i in sim_scores]
    return movies['title'].iloc[movie_indices]

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

Давайте попробуем рекомендовать фильм для миньонов:

des_recommendations('Minions')

В качестве рекомендаций мы получаем следующие мультфильмы / детские фильмы:

Если мы попробуем Темного рыцаря:

des_recommendations('The Dark Knight')

В качестве рекомендаций мы получаем в основном другие фильмы о Бэтмене:

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

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

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

Таким образом, CF может предсказать, насколько пользователю понравится определенный фильм, даже если пользователь еще не оценил его. Двигаясь дальше, чтобы начать работу в проекте CF, нам нужно загрузить другой набор данных из Kaggle здесь, в частности, набор данных rating_small.csv, потому что предыдущий набор данных не содержит функции User ID, которая необходима в проекте CF.

ratings = pd.read_csv('ratings_small.csv')

Нам также нужно будет импортировать библиотеку scikit-Surprise, чтобы использовать ее SVD и другие функции. Если вы не установили сюрприз, вы можете запустить следующий код:

pip install surprise

Затем мы можем импортировать библиотеки-сюрпризы:

from surprise import Reader, Dataset, SVD
from surprise.model_selection import cross_validate

Поскольку мы имеем дело с большим количеством данных о пользователях и продуктах, нам необходимо снизить вероятность проблем с масштабируемостью и разреженностью, реализовав разложение по сингулярным значениям (SVD), с помощью которого мы сможем проверить производительность набора данных, оценив RMSE (Root Среднеквадратичная ошибка) и MAE (Средняя абсолютная ошибка). Примечание. Чем ниже значения RMSE и MAE, тем выше производительность для набора данных.

reader = Reader()
data = Dataset.load_from_df(ratings[['userId', 'movieId', 'rating']], reader)
svd = SVD()
cross_validate(svd, data, measures=['RMSE', 'MAE'], cv=5)

Как мы видим, результат MAE и RMSE после реализации SVD меньше 1, что находится в приемлемом диапазоне:

Поскольку он показал хорошие результаты, давайте обучим наши данные:

train = data.build_full_trainset()
svd.fit(train)

Давайте проверим данные с идентификатором пользователя 1:

ratings[ratings['userId'] == 1]

А давайте сделаем прогноз для идентификатора пользователя 1 с идентификатором фильма 302:

svd.predict(1, 302, 3)

Мы получаем прогнозный оценочный рейтинг 2,87.

Вывод

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

Спасибо за чтение, надеюсь, вам понравится.