如何用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 相关文章推荐
pytorch cnn 识别手写的字实现自建图片数据
May 20 Python
Python3.6.0+opencv3.3.0人脸检测示例
May 25 Python
python操作mysql代码总结
Jun 01 Python
对Python 3.2 迭代器的next函数实例讲解
Oct 18 Python
使用django的ORM框架按月统计近一年内的数据方法
Jul 18 Python
解决Python logging模块无法正常输出日志的问题
Feb 21 Python
python 字典item与iteritems的区别详解
Apr 25 Python
Python爬虫JSON及JSONPath运行原理详解
Jun 04 Python
python进度条显示之tqmd模块
Aug 22 Python
python3从网络摄像机解析mjpeg http流的示例
Nov 13 Python
Python提取PDF指定内容并生成新文件
Jun 09 Python
解决Python保存文件名太长OSError: [Errno 36] File name too long
May 11 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
应用开发中涉及到的css和php笔记分享
2011/08/02 PHP
zend Framework中的Layout(模块化得布局)详解
2013/06/28 PHP
php绘图中显示不出图片的原因及解决
2014/03/05 PHP
PHP实现的迷你漂流瓶
2015/07/29 PHP
PHP环境搭建(php+Apache+mysql)
2016/11/14 PHP
使用PHP json_decode可能遇到的坑与解决方法
2017/08/03 PHP
php实现将数组或对象写入到文件的方法小结【三种方法】
2020/04/22 PHP
javascript &&和||运算法的另类使用技巧
2009/11/28 Javascript
javascript demo 基本技巧
2009/12/18 Javascript
{}与function(){}选用空对象{}来存放keyValue
2012/05/23 Javascript
用javascript添加控件自定义属性解析
2013/11/25 Javascript
javascript使用百度地图api和html5特性获取浏览器位置
2014/01/10 Javascript
判断输入的字符串是否是日期格式的简单方法
2016/07/11 Javascript
js导出excel文件的简洁方法(推荐)
2016/11/02 Javascript
通过原生JS实现为元素添加事件的方法
2016/11/23 Javascript
通过示例彻底搞懂js闭包
2017/08/10 Javascript
node.js-v6新版安装具体步骤(分享)
2017/09/06 Javascript
浅谈SpringMVC中post checkbox 多选框value的值(隐藏域方式)
2018/01/08 Javascript
p5.js入门教程之小球动画示例代码
2018/03/15 Javascript
JS执行控制之节流模式实例分析
2018/12/21 Javascript
NodeJS实现同步的方法
2019/03/02 NodeJs
VUE的history模式下除了index外其他路由404报错解决办法
2019/08/21 Javascript
浅谈vue中$bus的使用和涉及到的问题
2020/07/28 Javascript
python定时按日期备份MySQL数据并压缩
2019/04/19 Python
计算机二级python学习教程(2) python语言基本语法元素
2019/05/16 Python
python 通过视频url获取视频的宽高方式
2019/12/10 Python
pandas-resample按时间聚合实例
2019/12/27 Python
大学生求职推荐信
2013/11/27 职场文书
人口与计划生育目标管理责任书
2014/07/29 职场文书
纪念九一八事变演讲稿:忘记意味着背叛
2014/09/14 职场文书
缓刑人员思想汇报
2014/10/11 职场文书
英文慰问信
2015/02/14 职场文书
2015年幼儿园班主任工作总结
2015/05/12 职场文书
感谢师恩主题班会
2015/08/17 职场文书
导游词幽默开场白
2019/06/26 职场文书
Oracle中DBLink的详细介绍
2022/04/29 Oracle