Создайте простую систему рекомендаций на Python с помощью Pandas

Программа перевода самородков Python продукт pandas

Введение

Вы когда-нибудь задумывались, как Netflix рекомендует вам фильмы на основе фильмов, которые вы уже смотрели? Или как сайты электронной коммерции отображают такие параметры, как «Часто покупают вместе»? Они могут показаться простыми вариантами, но за кулисами реализован сложный набор статистических алгоритмов для прогнозирования этих рекомендаций. Такие системы называются системами гида по магазинам, рекомендательными системами или рекомендательными системами.Система гида по магазинамЭто одно из самых известных приложений в науке о данных и машинном обучении.

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

В настоящее время многие крупные технологические компании так или иначе используют рекомендательные системы. От Amazon (рекомендации продуктов) до YouTube (рекомендации видео) и Facebook (рекомендации друзей) вы найдете системы рекомендаций повсюду. Возможность рекомендовать пользователям релевантные продукты и услуги может стать огромным стимулом для компании, поэтому эта технология широко используется на многих веб-сайтах.

В этом посте мы увидим, как создать простую рекомендательную систему на Python.

Типы рекомендательных систем

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

Фильтровать по содержимому

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

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

Совместная фильтрация использует силу толпы. Интуиция, стоящая за совместной фильтрацией, заключается в том, что если пользователю А нравятся продукты X и Y, то, если пользователю B нравится продукт X, есть неплохая вероятность, что ему понравится и продукт Y.

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

Реализация системы рекомендаций фильмов на Python

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

Мы будем использовать набор данных MovieLens для решения этой проблемы. Чтобы загрузить этот набор данных, вы можете перейти к набору данныхДомойЗагрузите файл «ml-latest-small.zip», который содержит подмножество реального набора данных о фильмах и содержит 100 000 оценок для 9 000 фильмов от 700 пользователей.

При распаковке файлов вы увидите файлы «links.csv», «movies.csv», «ratings.csv» и «tags.csv», а также документ «README». В этой статье мы будем использовать файлы «movies.csv» и «ratings.csv».

Для сценариев в этой статье распакованная папка «ml-latest-small» была помещена в папку «Наборы данных» на диске «E».

Визуализация данных и предварительная обработка

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

import numpy as np
import pandas as pd

ratings_data = pd.read_csv("E:\Datasets\ml-latest-small\\ratings.csv")
ratings_data.head()

В приведенном выше скрипте мы используемБиблиотека пандизread_csv()Метод считывает файл «ratings.csv». Далее мы звонимread_csv()Объект dataframe, возвращаемый функциейhead()метод. Он покажет первые пять строк набора данных.

Результат выглядит следующим образом:

userId movieId rating timestamp
0 1 31 2.5
1 1 1029 3.0
2 1 1061 3.0
3 1 1129 2.0
4 1 1172 4.0

Как видно из вывода, файл «ratings.csv» содержит свойства userId, movieId, ratings и timestamp. Каждая строка набора данных соответствует баллу. Столбец userId содержит идентификатор оценивающего пользователя. Столбец movieId содержит идентификатор фильма, а столбец рейтинга — рейтинг пользователя. Оценки выставляются по шкале от 1 до 5. Последняя временная метка представляет собой время, когда пользователь поставил оценку.

Возникла проблема с этим набором данных. То есть он имеет идентификатор фильма, но не название фильма. Нам нужно название фильма, который мы хотим порекомендовать. И название фильма существует в файле «movies.csv». Давайте импортируем его и посмотрим, что там. Выполните следующий скрипт:

movie_names = pd.read_csv("E:\Datasets\ml-latest-small\\movies.csv")  
movie_names.head()  

Результат выглядит следующим образом:

movieId title genres
0 1 Toy Story (1995) Adventure|Animation|Children|Comedy|Fantasy
1 2 Jumanji (1995) Adventure|Children|Fantasy
2 3 Grumpier Old Men (1995) Comedy|Romance
3 4 Waiting to Exhale (1995) Comedy|Drama|Romance
4 5 Father of the Bride Part II (1995) Comedy

Как видите, набор данных содержит movieId, название фильма и его жанр. Нам нужен набор данных с userId, названием фильма и рейтингом. И нужная нам информация находится в двух разных объектах фрейма данных: «ratings_data» и «movie_names». Чтобы поместить нужную информацию в один фрейм данных, мы можем объединить два объекта фрейма данных на основе столбца movieId, поскольку он является общим для обоих объектов фрейма данных.

Мы можем использовать библиотеку Pandasmerge()функционируют следующим образом:

movie_data = pd.merge(ratings_data, movie_names, on='movieId')

Теперь давайте посмотрим на новый фрейм данных:

movie_data.head()

Результат выглядит следующим образом:

userId movieId rating timestamp title genres
0 1 31 2.5 1260759144 Dangerous Minds (1995) Drama
1 7 31 3.0 851868750 Dangerous Minds (1995) Drama
2 31 31 4.0 12703541953 Dangerous Minds (1995) Drama
3 32 31 4.0 834828440 Dangerous Minds (1995) Drama
4 36 31 3.0 847057202 Dangerous Minds (1995) Drama

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

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

movie_data.groupby('title')['rating'].mean().head()

Результат выглядит следующим образом:

title
"Great Performances" Cats (1998)           1.750000
$9.99 (2008)                               3.833333
'Hellboy': The Seeds of Creation (2004)    2.000000
'Neath the Arizona Skies (1934)            0.500000
'Round Midnight (1986)                     2.250000
Name: rating, dtype: float64

Вы можете видеть, что средние оценки не отсортированы. Отсортируем оценки по убыванию среднего рейтинга:

movie_data.groupby('title')['rating'].mean().sort_values(ascending=False).head()

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

title
Burn Up! (1991)                                     5.0
Absolute Giganten (1999)                            5.0
Gentlemen of Fortune (Dzhentlmeny udachi) (1972)    5.0
Erik the Viking (1989)                              5.0
Reality (2014)                                      5.0
Name: rating, dtype: float64

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

Теперь построим общее количество оценок фильма:

movie_data.groupby('title')['rating'].count().sort_values(ascending=False).head()

Выполнение приведенного выше скрипта возвращает следующие результаты:

title
Forrest Gump (1994)                          341
Pulp Fiction (1994)                          324
Shawshank Redemption, The (1994)             311
Silence of the Lambs, The (1991)             304
Star Wars: Episode IV - A New Hope (1977)    291
Name: rating, dtype: int64

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

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

ratings_mean_count = pd.DataFrame(movie_data.groupby('title')['rating'].mean())

Далее нам нужно добавить рейтинг фильма вratings_mean_countкадр данных. Выполните следующий скрипт для достижения:

ratings_mean_count['rating_counts'] = pd.DataFrame(movie_data.groupby('title')['rating'].count())

Теперь давайте еще раз взглянем на только что созданный фрейм данных.

ratings_mean_count.head()

Результат выглядит следующим образом:

title rating rating_counts
"Great Performances" Cats (1998) 1.750000 2
$9.99 (2008) 3.833333 3
'Hellboy': The Seeds of Creation (2004) 2.000000 1
'Neath the Arizona Skies (1934) 0.500000 1
'Round Midnight (1986) 2.250000 2

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

Давайте построим гистограмму количества оценок, представленных столбцом «rating_counts» в кадре данных выше. Выполните следующий скрипт:

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('dark')
%matplotlib inline

plt.figure(figsize=(8,6))
plt.rcParams['patch.force_edgecolor'] = True
ratings_mean_count['rating_counts'].hist(bins=50)

Вот вывод вышеуказанного скрипта:

Ratings histogram

На изображении выше видно, что большинство фильмов имеют менее 50 рейтингов. И очень мало фильмов с более чем 100 рейтингами.

Теперь построим гистограмму средних оценок. код показывает, как показано ниже:

plt.figure(figsize=(8,6))
plt.rcParams['patch.force_edgecolor'] = True
ratings_mean_count['rating'].hist(bins=50)

Результат выглядит следующим образом:

Average ratings histogram

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

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

plt.figure(figsize=(8,6))
plt.rcParams['patch.force_edgecolor'] = True
sns.jointplot(x='rating', y='rating_counts', data=ratings_mean_count, alpha=0.4)

Результат выглядит следующим образом:

Average ratings vs number of ratings

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

Найдите сходство между фильмами

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

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

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

user_movie_rating = movie_data.pivot_table(index='userId', columns='title', values='rating')
user_movie_rating.head()
title "Great Performances" Cats (1998) $9.99 (1998) 'Hellboy': The Seeds of Creation (2008) 'Neath the Arizona Skies (1934) 'Round Midnight (1986) 'Salem's Lot (2004) 'Til There Was You (1997) 'burbs, The (1989) 'night Mother (1986) (500) Days of Summer (2009) ... Zulu (1964) Zulu (2013)
userId
1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN
5 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN

Мы знаем, что каждая колонка содержит оценки всех пользователей для определенного фильма. Давайте найдем все оценки пользователей к фильму «Форрест Гамп (1994)» и найдем фильмы, похожие на него. Мы выбрали этот фильм, потому что у него было больше всего рейтингов, и мы хотели найти корреляции между фильмами с более высокими рейтингами.

Чтобы найти оценки пользователей для «Форреста Гампа (1994)», выполните следующий скрипт:

forrest_gump_ratings = user_movie_rating['Forrest Gump (1994)']

Приведенный выше скрипт вернет последовательность Pandas. Давайте посмотрим, как это выглядит.

forrest_gump_ratings.head()
userId
1    NaN
2    3.0
3    5.0
4    5.0
5    4.0
Name: Forrest Gump (1994), dtype: float64

Теперь давайте найдем все фильмы, похожие на «Форрест Гамп (1994)». Мы можем использовать что-то вродеcorrwith()Функция для поиска корреляции между оценками пользователей «Форест Гамп (1994)» и всеми остальными фильмами

movies_like_forest_gump = user_movie_rating.corrwith(forrest_gump_ratings)

corr_forrest_gump = pd.DataFrame(movies_like_forest_gump, columns=['Correlation'])
corr_forrest_gump.dropna(inplace=True)
corr_forrest_gump.head()

В приведенном выше сценарии мы сначала используемcorrwith()Функция извлекает список всех фильмов, связанных с «Форрест Гамп (1994)», и связанные с ними значения. Затем мы создали фрейм данных с названиями фильмов и соответствующими столбцами. Затем мы удалили все значения NA из фрейма данных и использовалиheadФункция отображает первые 5 строк.

Результат выглядит следующим образом:

title Correlation
$9.99 (2008) 1.000000
'burbs, The (1989) 0.044946
(500) Days of Summer (2009) 0.624458
*batteries not included (1987) 0.603023
...And Justice for All (1979) 0.173422

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

corr_forrest_gump.sort_values('Correlation', ascending=False).head(10)

Вот вывод вышеуказанного скрипта:

title Correlation
$9.99 (2008) 1.0
Say It Isn't So (2001) 1.0
Metropolis (2001) 1.0
See No Evil, Hear No Evil (1989) 1.0
Middle Men (2009) 1.0
Water for Elephants (2011) 1.0
Watch, The (2012) 1.0
Cheech & Chong's Next Movie (1980) 1.0
Forrest Gump (1994) 1.0
Warrior (2011) 1.0

Из вывода видно, что фильмы, тесно связанные с «Форрестом Гампом (1994)», не очень известны. Это говорит о том, что корреляция сама по себе не является хорошей мерой сходства, поскольку может быть один пользователь, который смотрел только «Форест Гамп» (1994) и другой фильм и оценил их оба по пятибалльной шкале.

Решение этой проблемы состоит в том, чтобы получить только релевантные фильмы с рейтингом не менее 50. Для этого мы будемrating_mean_countв кадре данныхrating_countsколонка к нашемуcorr_forrest_gumpв кадре данных. Выполните следующий скрипт:

corr_forrest_gump = corr_forrest_gump.join(ratings_mean_count['rating_counts'])
corr_forrest_gump.head()

Результат выглядит следующим образом:

title Correlation rating_counts
$9.99 (2008) 1.000000 3
'burbs, The (1989) 0.044946 19
(500) Days of Summer (2009) 0.624458 45
*batteries not included (1987) 0.603023 7
...And Justice for All (1979) 0.173422 13

Вы можете видеть, что фильм «9,99 долларов» с наивысшей релевантностью имеет всего 3 рейтинга. Это показывает, что только 3 пользователя поставили фильму «Форест Гамп (1994)» такую ​​же оценку, как «9,99 долларов». Однако мы можем сделать вывод, что нельзя сказать, что один продукт похож на другой, основываясь только на 3 оценках. Вот почему мы добавили столбец «rating_counts». Теперь давайте отфильтруем фильмы, связанные с «Форест Гамп (1994)» с рейтингом выше 50. Следующий код делает это:

corr_forrest_gump[corr_forrest_gump ['rating_counts']>50].sort_values('Correlation', ascending=False).head()

Вывод скрипта следующий:

title Correlation rating_counts
Forrest Gump (1994) 1.000000 341
My Big Fat Greek Wedding (2002) 0.626240 51
Beautiful Mind, A (2001) 0.575922 114
Few Good Men, A (1992) 0.555206 76
Million Dollar Baby (2004) 0.545638 65

Теперь вы можете увидеть на выходе фильм, тесно связанный с «Форрестом Гампом» (1994). Фильмы в списке являются одними из самых известных в Голливуде, а поскольку «Форест Гамп» (1994) также очень известен, есть большая вероятность, что эти фильмы связаны между собой.

в заключении

В этой статье мы узнали, что такое рекомендательная система и как ее создать на Python, используя только библиотеку Pandas. Стоит отметить, что созданная нами рекомендательная система очень проста. В реальных рекомендательных системах используются очень сложные алгоритмы, о которых мы поговорим в следующей статье.

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

Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.