如何在Python中构建一个简单的推荐系统
在本文中,我们将向读者介绍推荐系统。我们还将在Python中构建一个简单的推荐系统。该系统仅作为推荐系统的介绍。我们假设读者具有pandas和numpy等科学软件包的经验。
什么是推荐系统?
推荐系统是一种简单的算法,其目的是通过发现数据集中的模式向用户提供最相关的信息。该算法对项目进行评级,并向用户显示它们将给予很高的评级。实施建议的一个示例是,当您访问亚马逊并且您注意到某些项目正在向您推荐或Netflix向您推荐某些电影时。音乐流媒体应用程序(如Spotify和Deezer)也会使用它们来推荐您可能喜欢的音乐。
以下是推荐系统如何在电子商务网站环境中工作的非常简单的说明。
两个用户从电子商务商店购买相同的商品A和B. 当发生这种情况时,计算这两个用户的相似性指数。根据分数,系统可以将项目C推荐给其他用户,因为它检测到这两个用户在他们购买的项目方面是相似的。
不同类型的推荐引擎
最常见的推荐系统类型是基于内容和协同过滤的推荐系统。在协同过滤中,一组用户的行为用于向其他用户提出建议。建议基于其他用户的偏好。一个简单的例子是基于他们的朋友喜欢电影的事实向用户推荐电影。有两种类型的协作模型Memory-based方法和Model-based 的方法。memory-based 技术的优点是它们是易于实施,所得到的建议通常很容易解释。它们分为两个:
- 基于用户的协同过滤:在此模型中,基于产品已被类似于用户的用户所喜欢的事实向用户推荐产品。例如,如果德里克和丹尼斯喜欢相同的电影并且出现了德里克喜欢的新电影,那么我们可以向丹尼斯推荐这部电影,因为德里克和丹尼斯似乎喜欢同样的电影。
- 基于项目的协同过滤:这些系统根据用户之前的评级识别类似项目。例如,如果用户A,B和C对书籍X和Y给出5星评级,那么当用户D购买书籍Y时他们也得到购买书籍X的建议,因为系统根据评级将书籍X和Y识别为相似用户A,B和C.
Model-based方法基于矩阵分解,并且更好地处理稀疏性。它们是使用数据挖掘,机器学习算法开发的,用于预测用户对未评级项目的评级。在这种方法中,诸如降维的技术被用于提高准确性。这种基于模型的方法的示例包括决策树,基于规则的模型,贝叶斯方法和潜在因子模型。
基于内容的系统使用元数据,如流派、制作人、演员、音乐家等来推荐电影或音乐。这样的建议可以是,比如推荐《无尽的战争》(Infinity War),它的主角是凡·迪塞尔(Vin Disiel),因为有人看到并喜欢《狂暴战士》(Furious)的命运。同样,你也可以从某些艺术家那里得到音乐推荐,因为你喜欢他们的音乐。基于内容的系统是基于这样一种想法:如果你喜欢某样东西,你很可能会喜欢与之相似的东西。
用于构建推荐系统的数据集
在本教程中,我们将使用MovieLes数据集(https://grouplens.org/datasets/movielens/)。该数据集由明尼苏达大学的Grouplens研究小组整理。它包含1,10和20,000万个评级。Movielens还有一个网站,您可以在其中注册,撰写评论并获取电影推荐。您可以从Dataquest的数据资源中找到更多用于各种数据科学任务的数据集。
构建推荐系统的演练
我们将使用movielens构建一个基于项目相似度的简单推荐系统。我们需要做的第一件事就是导入pandas和numpy。
import pandas as pd import numpy as np import warnings warnings.filterwarnings('ignore')
接下来,我们使用panda read_csv()实用程序加载数据集。数据集是制表符分开的,所以我们传入 到sep参数。然后使用names参数传入列名。Python代码如下:
df = pd.read_csv('u.data', sep=' ', names=['user_id','item_id','rating','titmestamp'])
现在让我们查看我们正在处理的数据
df.head()
如果我们能看到电影的片名而不是仅仅处理id就好了。让我们加载影片标题并将其与此数据集合并。
movie_titles = pd.read_csv('Movie_Titles') movie_titles.head()
由于item_id列是相同的,我们可以在此列上合并这些数据集。
df = pd.merge(df, movie_titles, on='item_id') df.head()
让我们看看每列代表什么:
- user_id - 评价电影的用户的ID。
- item_id - 电影的ID。
- rating - 用户给予电影的评级,介于1和5之间。
- timestamp - 电影评分的时间。
- title - 电影的标题。
使用describe或info命令我们可以得到我们的数据集的简要描述。这对于让我们了解我们正在使用的数据集非常重要。
df.describe()
我们可以看出平均评分为3.52,最大值为5.我们还看到数据集有100003条记录。
现在让我们创建一个dataframe ,其中包含每部电影的平均评分和评分数。我们将使用这些评级来计算以后的电影之间的相关性。相关性是一种统计指标,表示两个或多个变量一起波动的程度。具有高相关系数的电影是彼此最相似的电影。在我们的例子中,我们将使用Pearson相关系数。该数字将介于-1和1之间.1表示正线性相关,而-1表示负相关。0表示没有线性相关。因此,具有零相关性的电影完全不相似。为了创建这个dataframe ,我们使用pandas groupby。我们按照分组对数据集进行title 列分组并计算其平均值以获得每部电影的平均评分。Python示例如下:
ratings = pd.DataFrame(df.groupby('title')['rating'].mean()) ratings.head()
接下来我们希望看到每部电影的评分数量。我们通过创建一个number_of_ratings列来完成此操作。这很重要,这样我们就可以看到电影的平均评分与电影获得的评分数量之间的关系。五星级电影很有可能只被一个人评价。因此,对于该电影具有5星级电影进行分类在统计上是不正确的。因此,在构建推荐系统时,我们需要设置最小额定值的阈值。为了创建这个新列,我们使用pandas groupby实用程序。我们按title列分组,然后使用该count函数计算每部电影获得的评分数。然后我们使用该head()函数查看新的dataframe 。
ratings['number_of_ratings'] = df.groupby('title')['rating'].count() ratings.head()
现在让我们使用pandas来绘制直方图,以显示评级的分布,Python代码如下:
import matplotlib.pyplot as plt %matplotlib inline ratings['rating'].hist(bins=50)
我们可以看到大多数电影的评分在2.5到4之间。接下来,让我们以类似的方式可视化number_of_ratings列。
ratings['number_of_ratings'].hist(bins=60)
从上面的直方图中可以清楚地看出,大多数电影的收视率都很低。评分最高的电影是最著名的电影。
现在让我们检查电影评级与评分数量之间的关系。我们通过使用seaborn绘制散点图来做到这一点。Seaborn使我们能够使用jointplot()函数执行此操作。
import seaborn as sns sns.jointplot(x='rating', y='number_of_ratings', data=ratings)
从图中我们可以看出,它们是电影平均评分与评分数量之间的正相关关系。该图表示电影获得的评分越高,其获得的平均评分越高。特别是在为每部电影选择评级数量的阈值时,这一点很重要。
现在让我们快速进行并创建一个简单的基于项目的推荐系统。为了做到这一点,我们需要将数据集转换为一个矩阵,以电影标题为列,以user_id为索引,以评级为值。通过这样做,我们将得到一个dataframe,其中列是movie标题,行是user id。每个栏目代表所有用户对一部电影的评分。如果用户没有对某一部电影进行评分,该评分以NAN的形式出现。我们将使用这个矩阵来计算单个电影的评级与矩阵中其他电影的评级之间的相关性。我们使用panda pivot_table实用程序创建电影矩阵。
movie_matrix = df.pivot_table(index='user_id', columns='title', values='rating') movie_matrix.head()
接下来,让我们来看看评分最高的电影,并从中选出两部在这个简单的推荐系统中使用。我们使用panda sort_values工具,并将ascending设置为false,以便从评分最高的电影中进行排列。然后我们使用head()函数查看前10名。
ratings.sort_values('number_of_ratings', ascending=False).head(10)
假设用户看过《Air Force One》(1997)和《Contact》(1997)。我们想根据这个观看历史向这个用户推荐电影。我们的目标是寻找与Contact(1997)和Air Force One(1997)相似的电影。我们可以通过计算这两个电影的评级和数据集中其他电影的评级之间的相关性来实现这一点。第一步是用movie_matrix中的这些电影的评级创建一个dataframe。
AFO_user_rating = movie_matrix['Air Force One (1997)'] contact_user_rating = movie_matrix['Contact (1997)']
现在我们有了dataframes,显示了user_id和他们给这两个电影的评级。
AFO_user_rating.head() contact_user_rating.head()
为了计算两个dataframe之间的相关性,我们使用pandas corwith函数。Corrwith计算两个dataframe对象的行或列的成对相关性。让我们使用此功能来获得每部电影的评级与Air Force One电影的评级之间的相关性。
similar_to_air_force_one=movie_matrix.corrwith(AFO_user_rating)
我们可以看到Air Force One电影和Til There Was You(1997)之间的相关性是0.867。这表明这两部电影之间有很强的相似性。
similar_to_air_force_one.head()
让我们继续前进并计算Contact(1997)评级与其他电影评级之间的相关性。程序与上面使用的程序相同。
similar_to_contact = movie_matrix.corrwith(contact_user_rating)
我们从计算中发现,Contact(1997)和Til There Was You(1997)之间存在非常强的相关性(0.904)。
similar_to_contact.head()
如前所述,我们的矩阵有很多缺失值,因为并非所有用户都对所有电影进行了评分。因此,我们删除这些空值并将相关结果转换为数据帧,以使结果看起来更具吸引力。Python代码如下:
corr_contact = pd.DataFrame(similar_to_contact, columns=['Correlation']) corr_contact.dropna(inplace=True) corr_contact.head() corr_AFO = pd.DataFrame(similar_to_air_force_one, columns=['correlation']) corr_AFO.dropna(inplace=True) corr_AFO.head()
上面的这两个dataframes分别向我们展示了与Contact(1997)和Air Force One(1997)电影最相似的电影。然而,我们遇到了一个挑战,因为有些电影的收视率非常低,最终可能因为一两个人给他们5星评级而被推荐。我们可以通过设置评级数量的阈值来解决这个问题。从早期的柱状图中我们看到评级数量从100急剧下降。因此,我们将此设置为阈值,但是这是一个你可以设置的数字,直到你得到一个合适的选项。
corr_AFO = corr_AFO.join(ratings['number_of_ratings']) corr_contact = corr_contact.join(ratings['number_of_ratings']) corr_AFO .head() corr_contact.head()
我们现在将获得与Air Force One(1997)最相似的电影,将它们限制为至少有100条评论的电影。然后我们按correlation列对它们进行排序并查看前10个。
corr_AFO[corr_AFO['number_of_ratings'] > 100].sort_values(by='correlation', ascending=False).head(10)
我们注意到Air Force One(1997)与自身有完美的相关性,这并不奇怪。Air Force One(1997)的下一部最相似的电影是Hunt for Red October,The(1990),相关系数为0.554。显然,通过更改评论数量的阈值,我们可以从之前的方式获得不同的结果。限制评级数量可以让我们获得更好的结果,我们可以自信地向观看Air Force One(1997)的人推荐上述电影。
现在让我们对Contact(1997)电影做同样的事情,看看与它最相关的电影。
corr_contact[corr_contact['number_of_ratings'] > 100].sort_values(by='Correlation', ascending=False).head(10)
我们再一次得到不同的结果。与Contact(1997)最相似的电影是费城(1993),相关系数为0.446,有137个评级。所以,如果有人喜欢Contact(1997),我们可以向他们推荐上述电影。
显然,这是构建推荐系统的一种非常简单的方法,并且不符合行业标准。
如何改进推荐系统
可以通过构建Memory-Based 协同过滤的系统来改进该系统。在这种情况下,我们将数据划分为训练集和测试集。然后我们使用诸如余弦相似性的技术来计算电影之间的相似性。另一种方法是构建基于模型的协同过滤系统。这基于矩阵分解。矩阵分解在处理可扩展性和稀疏性方面比前者好。然后,您可以使用诸如均方根误差(RMSE)等技术来评估模型。
最后
还有其他用于构建推荐系统的技术。深度学习是这样做的方法之一,尤其是当您拥有大量数据集时。用于构建高级推荐系统的一些算法包括自动编码器和限制玻尔兹曼机器