如何用Python来搭建一个简单的推荐系统


Posted in Python onAugust 07, 2019

在这篇文章中,我们会介绍如何用Python来搭建一个简单的推荐系统。

本文使用的数据集是MovieLens数据集,该数据集由明尼苏达大学的Grouplens研究小组整理。它包含1,10和2亿个评级。 Movielens还有一个网站,我们可以注册,撰写评论并获得电影推荐。接下来我们就开始实战演练。

在这篇文章中,我们会使用Movielens构建一个基于item的简易的推荐系统。在开始前,第一件事就是导入pandas和numPy。

import pandas as pd import numpy as np import warnings warnings.filterwarnings('ignore')

接下来,我们使用pandas read_csv()加载数据集。数据集由制表符分隔,所以我们将\ t传递给sep参数。然后,使用names参数传入列名。

df = pd.read_csv('u.data', sep='\t', 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()

可以看出,数据集共有100003条记录,电影的平均评分介于3.52-5之间。

现在我们再创建一个dataframe,其中包含每部电影的平均评分和评分数量。之后,这些评分将用来计算电影之间的相关性。相关性是一种统计指标,表示两个或多个变量一起波动的程度。相关系数越高,电影越为相似。

以下例子将使用Pearson相关系数 (Pearson correlation coefficient),该数字介于-1和1之间,1表示正线性相关,-1表示负相关, 0表示没有线性相关。也就是说,具有零相关性的电影完全不相似。

我们会使用pandas groupby 功能来创建dataframe。按照标题对数据集进行分组,并计算其平均值获得每部电影的平均评分。

ratings = pd.DataFrame(df.groupby('title')['rating'].mean()) ratings.head()

接下来我们创建number_of_ratings列,这样就能看到每部电影的评分数量。完成这步操作后,就可以看到电影的平均评分与电影获得的评分数量之间的关系。五星级电影很有可能只被一个人评价,而这种五星电影在统计上是不正确的。

因此,在构建推荐系统时,我们需要设置阈值。我们可以使用pandas groupby功能来创建新列,然后按标题栏分组,使用计数函数计算每部电影的评分。之后,便可以使用head()函数查看新的dataframe。

rating ['number_of_ratings'] = df.groupby('title')['rating'].count() ratings.head()

接下来我们使用pandas绘制功能来绘制直方图,显示评级的分布:

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绘制散点图,然后使用jointplot()函数执行此操作。

import seaborn as sns sns.jointplot(x='rating', y='number_of_ratings', data=ratings)

从图中我们可以看出,电影平均评分与评分数量之间呈正相关关系,电影获得的评分数量越多,其平均评分越高。

创建基于item的简易推荐系统

接下来我们会快速创建一个基于item的简单的推荐系统。

首先,我们需要将数据集转换为矩阵,电影标题为列,user_id为索引,评级为值。完成这一步,我们将得到一个dataframe,其中列是电影标题,行是用户ID。每列代表所有用户对电影的所有评级。评级为NAN表示用户未对这部电影评分。

我们可以用该矩阵来计算单个电影的评级与矩阵中其余电影的相关性,该矩阵可以通过pandas pivot_table实现。

movie_matrix = df.pivot_table(index ='user_id',columns ='title',values ='rating') movie_matrix.head()

接下来让我们找到评分数量最多的电影,并选择其中的两部电影。然后使用pandas sort_values并将升序设置为false,以便显示评分最多的电影。然后使用head()函数来查看评分数目最多的前十部电影。

ratings.sort_values('number_of_ratings', ascending=False).head(10)

假设一个用户曾看过Air Force One(1997)和Contact(1997),我们想根据这两条观看记录向该用户推荐其他类似的电影,那么这一点可以通过计算这两部电影的评级与数据集中其他电影的评级之间的相关性来实现。第一步是创建一个dataframe,其中包含来自movie_matrix的这些电影的评级。

AFO_user_rating = movie_matrix['Air Force One (1997)'] contact_user_rating = movie_matrix['Contact (1997)']

Dataframe可以显示user_id和这两部电影的评分。

AFO_user_rating.head() contact_user_rating.head()

使用pandas corwith功能计算两个dataframe之间的相关性。有了这一步,就能够获得每部电影的评级与Air Force One电影的评级之间的相关性。

similar_to_air_force_one = movie_matrix.corrwith(AFO_user_rating)

可以看到,Air Force One电影和Till 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)和Till There Was You(1997)之间存在非常强的相关性(0.904)。

similar_to_contact.head()

前边已经提到,并非所有用户都对所有电影进行了评分,因此,该矩阵中有很多缺失值。为了让结果看起来更有吸引力,删除这些空值并将相关结果转换为dataframe。

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()

上面这两个dataframe分别展示了与Contact(1997)和Air Force One(1997)电影最相似的电影。然而,问题出现了,有些电影的实际质量非常低,但可能因为一两位用户给他们5星评级而被推荐。

这个问题可以通过设置评级数量的阈值来解决。从早期的直方图中看到,评级数量从100开始急剧下降。因此可以将此设置为阈值,但是也可以考虑其他合适的值。为此,我们需要将两个dataframe与rating datframe中的number_of_ratings列一起加入。

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条评论的电影中,然后可以按相关列对它们进行排序并查看前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,相关系数为0.554。

显然,通过更改评论数量的阈值,我们可以按之前的方式得到不同的结果。限制评级数量可以让我们获得更好的结果。

现在重复上边的步骤,可以看到与Contact(1997)电影最相关的电影:

corr_contact [corr_contact ['number_of_ratings']> 100] .sort_values(by ='Correlation',ascending = False).head(10)

与Contact(1997)最相似的电影是Philadelphia(1993),相关系数为0.446,有137个评级。所以,如果有人喜欢Contact(1997),我们可以向他们推荐上述电影。

以上是构建推荐系统的一种非常简单的方法,但并不符合行业标准。后续的话我们可以通过构建基于存储器的协同过滤系统来改进该系统。在这种情况下,将数据划分为训练集和测试集,使用诸如余弦相似性来计算电影之间的相似性;或者构建基于模型的协作过滤系统,然后使用Root Mean Squared Error(RMSE)等技术评估模型。

Github: https://github.com/mwitiderrick/simple-recommender-

英文:How to build a Simple Recommender System in Python

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中wx将图标显示在右下角的脚本代码
Mar 08 Python
Python中的FTP通信模块ftplib的用法整理
Jul 08 Python
不可错过的十本Python好书
Jul 06 Python
tensorflow中next_batch的具体使用
Feb 02 Python
Python迭代器与生成器基本用法分析
Jul 26 Python
python3 面向对象__类的内置属性与方法的实例代码
Nov 09 Python
Python爬虫 批量爬取下载抖音视频代码实例
Aug 16 Python
Python队列、进程间通信、线程案例
Oct 25 Python
tensorflow通过模型文件,使用tensorboard查看其模型图Graph方式
Jan 23 Python
浅析Django 接收所有文件,前端展示文件(包括视频,文件,图片)ajax请求
Mar 09 Python
django ORM之values和annotate使用详解
May 19 Python
基于Python中random.sample()的替代方案
May 23 Python
PIL对上传到Django的图片进行处理并保存的实例
Aug 07 #Python
django 实现将本地图片存入数据库,并能显示在web上的示例
Aug 07 #Python
Python学习笔记之Django创建第一个数据库模型的方法
Aug 07 #Python
django将网络中的图片,保存成model中的ImageField的实例
Aug 07 #Python
Python学习笔记之文件的读写操作实例分析
Aug 07 #Python
详解python中__name__的意义以及作用
Aug 07 #Python
Pandas0.25来了千万别错过这10大好用的新功能
Aug 07 #Python
You might like
自定义PHP分页函数
2006/10/09 PHP
用PHP和ACCESS写聊天室(六)
2006/10/09 PHP
php中simplexml_load_string使用实例分享
2014/02/13 PHP
PHP命名空间定义与用法实例分析
2019/08/14 PHP
js+数组实现网页上显示时间/星期几的实用方法
2013/01/18 Javascript
js判断上传文件类型判断FileUpload文件类型代码
2014/05/20 Javascript
jQuery中:enabled选择器用法实例
2015/01/04 Javascript
jQuery检测输入的字符串包含的中英文的数量
2015/04/17 Javascript
javascript数组去重方法汇总
2015/04/23 Javascript
Angularjs过滤器使用详解
2016/05/25 Javascript
jQuery插件版本冲突的处理方法分析
2017/01/16 Javascript
基于layer.js实现收货地址弹框选择然后返回相应的地址信息
2017/05/26 Javascript
Angular.js ng-file-upload结合springMVC的使用教程
2017/07/10 Javascript
浅谈Angular4中常用管道
2017/09/27 Javascript
AjaxFileUpload.js实现异步上传文件功能
2019/04/19 Javascript
浅谈layui 绑定form submit提交表单的注意事项
2019/10/25 Javascript
vue 百度地图(vue-baidu-map)绘制方向箭头折线实例代码详解
2020/04/28 Javascript
vue $mount 和 el的区别说明
2020/09/11 Javascript
Element-ui upload上传文件限制的解决方法
2021/01/22 Javascript
PyQt5打开文件对话框QFileDialog实例代码
2018/02/07 Python
Python namedtuple命名元组实现过程解析
2020/01/08 Python
python实现翻译word表格小程序
2020/02/27 Python
Python 转移文件至云对象存储的方法
2021/02/07 Python
简单的HTML5初步入门教程
2015/09/29 HTML / CSS
宝拉珍选英国官网:Paula’s Choice英国
2019/05/29 全球购物
UNIX操作系统结构由哪几部分组成
2016/02/17 面试题
党员年终民主评议的自我评价
2013/11/05 职场文书
大学生毕业自我鉴定范文
2014/02/03 职场文书
2014年师德承诺书
2014/05/23 职场文书
组织鉴定材料
2014/06/02 职场文书
房地产端午节活动方案
2014/08/24 职场文书
基层领导干部“四风”问题批评与自我批评
2014/09/23 职场文书
重阳节演讲稿:尊敬帮助老人 弘扬传统美德
2014/09/25 职场文书
员工试用期工作总结
2019/06/20 职场文书
react中props 的使用及进行限制的方法
2021/04/28 Javascript
Python函数对象与闭包函数
2022/04/13 Python