使用Pandas构建推荐引擎
在这篇文章中,我们学习如何使用Pandas从头开始建立一个基本的推荐引擎。
使用Pandas构建电影推荐引擎
推荐引擎或推荐系统或推荐人系统是一个根据每个用户的喜好来预测或过滤偏好的系统。推荐系统通过协作过滤或基于内容的过滤,监督提供建议的索引。
推荐引擎是机器学习中最流行和最广泛使用的应用之一。几乎所有的大型科技公司,如电子商务网站、Netflix、Amazon Prime等都使用推荐引擎来向用户推荐合适的项目或电影。它是基于类似类型的用户更有可能对类似的搜索项目或实体有类似的评价这一本能。
现在让我们开始使用pandas创建我们非常基本和简单的推荐引擎。让我们专注于提供一个简单的推荐引擎,根据相关性和评分数量来呈现与某一对象最相似的东西,在本例中是电影。它只是告诉人们哪些电影被认为与用户的电影选择相当。
基于人气的过滤
基于人气的过滤是建立一个推荐系统的最基本和不太有用的过滤技术之一。它基本上可以过滤掉那些最流行的项目,并隐藏其他的项目。例如,在我们的电影数据集中,如果一部电影被大多数用户评分,这意味着它被许多用户观看过,而且现在正处于流行阶段。因此,只有那些有最多评分的电影才会被推荐系统推荐给用户。由于它对用户的某些特殊口味不敏感,所以缺乏个性化。
示例:
首先,我们将导入python的pandas库,在它的帮助下我们将创建推荐引擎。然后,我们在下面的代码中从给定的路径加载数据集,并在其中添加列名。
# import pandas library
import pandas as pd
# Get the column names
col_names = ['user_id', 'item_id', 'rating', 'timestamp']
# Load the dataset
path = 'https://media.geeksforgeeks.org/wp-content/uploads/file.tsv'
ratings = pd.read_csv(path, sep='\t', names=col_names)
# Check the head of the data
print(ratings.head())
# Check out all the movies and their respective IDs
movies = pd.read_csv(
'https://media.geeksforgeeks.org/wp-content/uploads/Movie_Id_Titles.csv')
print(movies.head())
# We merge the data
movies_merge = pd.merge(ratings, movies, on='item_id')
movies_merge.head()
输出
现在我们将根据电影的评分数量对电影进行排名。由于我们正在做基于人气的过滤,被更多用户观看的电影将有更多的评分。
pop_movies = movies_merge.groupby("title")
pop_movies["user_id"].count().sort_values(
ascending=False).reset_index().rename(
columns={"user_id": "score"})
pop_movies['Rank'] = pop_movies['score'].rank(
ascending=0, method='first')
pop_movies
输出
然后,我们将评分数最多的前10部电影可视化。
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.barh(pop_movies['title'].head(6),
pop_movies['score'].head(6),
align='center',
color='RED')
plt.xlabel("Popularity")
plt.title("Popular Movies")
plt.gca().invert_yaxis()
输出
协作过滤
基于用户过滤
这些技术向用户推荐匹配用户所选择的结果。我们可以应用皮尔逊相关或余弦相似性来估计两个用户之间的相似性。在基于用户的协同过滤中,我们找到了用户之间的相似性或相似性分数。协同过滤考虑到群众的力量。例如,如果许多人同时观看电子书A和B,而一个新用户只读B书,那么推荐引擎也会建议该用户阅读A书。
基于项目的协同过滤
基于项目的协同过滤不是计算不同用户之间的相似度,而是根据它们与目标用户排名的项目的相似度来推荐项目。同样,相似度也可以用皮尔逊相关度或余弦相似度来计算。例如,如果用户A喜欢电影P,而新用户B与A相似,那么推荐者将向用户B推荐电影P。
下面的代码演示了基于用户项目的协同过滤。
示例:
首先,我们将导入python的pandas库,在它的帮助下,我们将创建一个推荐引擎。然后,我们在下面的代码中从给定的路径加载数据集,并在其中添加列名。
# import pandas library
import pandas as pd
# Get the column names
col_names = ['user_id', 'item_id',
'rating', 'timestamp']
# Load the dataset
path = 'https://media.geeksforgeeks.org/\
wp-content/uploads/file.tsv'
ratings = pd.read_csv(path, sep='\t',
names=col_names)
# Check the head of the data
print(ratings.head())
# Check out all the movies and their respective IDs
movies = pd.read_csv(
'https://media.geeksforgeeks.org/\
wp-content/uploads/Movie_Id_Titles.csv')
print(movies.head())
输出
现在我们根据 item_id 合并这两个数据集,item_id 是两个数据集的共同主键。
movies_merge = pd.merge(ratings, movies,
on='item_id')
movies_merge.head()
输出
在这里,我们计算出对每部电影的评分的平均值。然后,我们计算出每部电影的评分数量。我们按照升序对它们进行排序,正如我们在输出中看到的那样。
print(movies_merge.groupby('title')[
'rating'].mean().sort_values(
ascending=False).head())
print(movies_merge.groupby('title')[
'rating'].count().sort_values(
ascending=False).head())
输出
现在,我们创建了一个新的数据框架,名为Rates_mean_count_data,并在每个电影标题旁边添加了新的评级平均值和评级计数列,因为这两个参数是过滤出最佳建议给用户的必要条件。
ratings_mean_count_data = pd.DataFrame(
movies_merge.groupby('title')['rating'].mean())
ratings_mean_count_data['rating_counts'] = pd.DataFrame(
movies_merge.groupby('title')['rating'].count())
ratings_mean_count_data
输出
在新创建的数据框中,我们可以看到电影以及评价的平均值和评价的数量。现在我们想创建一个矩阵来查看每个用户对每部电影的评分。要做到这一点,我们将执行以下代码。
user_rating = movies_merge.pivot_table(
index='user_id', columns='title', values='rating')
user_rating.head()
输出
这里的每一栏都包含了所有用户对某部电影的评分,使我们很容易找到我们选择的电影的评分。
这里的每一栏都包含了所有用户对某部电影的评分,使我们很容易找到我们选择的电影的评分。
因此,我们将看到《星球大战》(1977)的评分,因为它的评分最高。因为我们想找到收视率最高的电影之间的关联性,这将是一个很好的方法。我们将看到前25个评分。
Star_Wars_ratings = user_rating['Star Wars (1977)']
Star_Wars_ratings.head(15)
输出
现在我们将使用corrwith()函数找到与《星球大战》(1977)相关的电影。接下来,我们将相关值存储在一个名为corr_Star_Wars的新数据框中的Correlation列下。我们从新的数据集中删除了NaN值。
我们使用参数’ascending=False’将与《星球大战》(1977)高度相关的前10部电影按升序显示出来。
movies_like_Star_Wars = user_rating.corrwith(Star_Wars_ratings)
corr_Star_Wars = pd.DataFrame(movies_like_Star_Wars,
columns=['Correlation'])
corr_Star_Wars.dropna(inplace=True)
corr_Star_Wars.head(10)
corr_Star_Wars.sort_values('Correlation',
ascending=False).head(25)
输出
从上面的输出结果中,我们可以看到,与《星球大战》(1977)高度相关的电影并不都是著名的和知名的。
可能有这样的情况:只有一个用户观看了某部电影,并给它一个5星的评价。在这种情况下,这将不是一个有效的评级,因为没有其他用户观看过它。
因此,仅有相关性可能不是一个筛选出最佳建议的好指标。因此,我们在数据框架中增加了rating_counts这一列,以便在考虑相关性的同时考虑评分的数量。
corr_Star_Wars_count = corr_Star_Wars.join(
ratings_mean_count_data['rating_counts'])
我们假定,值得观看的电影至少会有一些评分大于100的电影。因此,下面的代码可以过滤出与100个以上用户的评分最相关的电影。
corr_Star_Wars_count[corr_Star_Wars_count[
'rating_counts'] > 100].sort_values(
'Correlation', ascending=False).head()
corr_Star_Wars_count = corr_Star_Wars_count.reset_index()
corr_Star_Wars_count
输出
我们可以更直观地看到最后一组推荐的电影
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.barh(corr_Star_Wars_count['title'].head(10),
abs(corr_Star_Wars_count['Correlation'].head(10)),
align='center',
color='red')
plt.xlabel("Popularity")
plt.title("Top 10 Popular Movies")
plt.gca().invert_yaxis()
输出
因此,上述电影将被推荐给刚刚看完或已经看完《星球大战》(1977)的用户。通过这种方式,我们可以用pandas建立一个非常基本的推荐系统。对于实时推荐引擎来说,pandas肯定不能满足需求。为此,我们将不得不实施复杂的机器学习算法和框架。