Just Do IT !

基于PySpark的电影推荐引擎

字数统计: 1.4k阅读时长: 5 min
2019/10/10 Share

相关知识

推荐引擎是最常见的机器学习应用,我们可以在各大购物网站上看见这方面的应用。

Spark MLlib支持ALS(Alternating Least Squares)推荐算法,是机器学习的协同过滤推荐算法。机器学习的协同过滤推荐算法通过观察所有用户给产品的评价来推断每个用户的喜好,并向每个用户分别推荐多个合适的产品,也可以把某个产品推荐给多个用户。

image

系统环境

Linux Centos7
Python 3.7.3
Anaconda
Spark2.4.2
IPython Notebook

任务步骤

前期准备

  1. 将hadoop相关服务打开

在hadoop/sbin目录下./start-all.sh

  1. 启动mysql服务
  2. 将文件上传到hdfs中

命令:hadoop fs -put /ml-100k(ml-100k的目录) /

  1. 开启PySpark

代码调试

我们使用sc.textFile读取ml-100k

我们使用sc.textFile读取HDFS上的ml-100k数据集中的u.data,并且查看数据项数

1
2
rawUserData = sc.textFile("hdfs://172.18.74.236:9000/ml-100k/u.data")  
rawUserData.count()

从以上运行结果中可以看到共有100000项评分数据。

查看u.data第一项数据

1
rawUserData.first()

以上4个字段分别是:用户id、项目id、评分、日期时间,\t为分隔符。

导入Rating模块

1
from pyspark.mllib.recommendation import Rating

读取rawUserData前三个字段,按照用户、产品、用户对此产品的评价来编写rawRatings

1
2
rawRatings = rawUserData.map(lambda line:line.split("\t")[:3])  
rawRatings.take(5)

以上程序显示了前5项rawRatings数据。上列命令的详细说明如下:

image

准备ALS训练数据

ALS训练数据格式是RatingRDD数据类型,Rating定义如下:

image

使用下列命令编写ratingsRDD

1
2
ratingsRDD = rawRatings.map(lambda x:(x[0],x[1],x[2]))  
ratingsRDD.take(5)

以上运行结果显示共有100000项评价

查看不重复用户数

x[0]是用户字段,可以先用.map(lambdax:x[0])转换为用户数据,再使用.distinct()筛选出不重复的数据,最后显示numUsers

1
2
numUsers = ratingsRDD.map(lambda x:x[0]).distinct().count()  
numUsers

以上运行结果显示共有943个不重复用户

查看不重复电影数

x[1]是电影字段,可以先使用.map(lambda x:x[1])转换为电影数据,再使用.distinct()筛选出不重复的数据

1
2
numMovies = ratingsRDD.map(lambda x:x[1]).distinct().count()  
numMovies

如何训练模型

如图,我们将使用rawUserData数据以map转换为rawRatings,再改用map转换为ALS训练数据格式RDD[Rating]。然后使用ALS.train进行训练,训练完后就会创建推荐引擎模型MatrixFactorizationModel。

image

导入ALS模块

1
from pyspark.mllib.recommendation import ALS

使用ALS.train介绍

我们将使用ALS.train命令进行训练。ALS.train可分为显式评分与隐式评分训练。

显式评分(Explicit Rating)训练

ALS.train(ratings,rank,iterations=5,lambda_=0.01):

返回:MatrixFactorizationModel

隐式评分(Implicit Rating)训练

ALS.trainImplicit(ratings,rank,iterations=5,lambda_=0.01):

返回:MatrixFactorizationModel

两种评分训练的作用都是训练数据并返回模型

image

我们可以使用ALS.train命令并传入之前创建的ratingsRDD进行训练,训练完成后返回model

1
2
model = ALS.train(ratingsRDD,10,10,0.01)  
print(model)

如何使用模型进行推荐

前面我们已经训练完成并建立了模型,接下来将使用此模型进行推荐

针对用户推荐电影

我们可以针对每个会员定期发送消息,或在会员登录时向会员推送可能会感兴趣的电影。

针对用户推荐电影,我们可以使用model.recommendProducts方法来推荐,说明如下表所示

MatrixFactorizationModel.recommendProducts(user:Int,num:Int):输入参数user,针对此user推荐给他有可能感兴趣的产品。

使用训练完的模型,向用户100推荐他可能感兴趣的前5部电影,传入参数(user=100,num=5)

1
model.recommendProducts(100,5)

以上执行结果显示,第1项数据是系统针对此用户首先推荐的产品,其意义是推荐给用户ID 100,产品ID1268,推荐评分大约为6.76,推荐评分越高,代表系统越优先推荐此产品

查看针对用户推荐产品的评分

我们可以查询系统对用户推荐产品的评分。例如,我们查询上一步骤的第一项,系统针对用户100推荐产品1141的评分

1
model.predict(100,1141)

参数说明:

image

使用训练完的模型,推荐对电影200感兴趣的前5个用户,传入参数(produce=200,num=5)

1
model.recommendUsers(product=200,num=5)

以上运行结果显示,第一项数据是系统针对电影推荐给用户。其意思是针对电影ID200推荐给用户ID818,推荐评分大约为7.4

显示推荐的电影名称

之前的例子只显示推荐电影的ID,下面我们使用u.item数据显示推荐电影的名称

使用sc.textFile将u.item文本文件导入itemRDD

1
2
itemRDD = sc.textFile("hdfs://172.18.74.236:9000/ml-100k/u.item")  
itemRDD.count()

为了显式推荐电影的名称,我们创建“电影ID与名称”的字典

1
2
movieTitle=itemRDD.map(lambda line:line.split("|")).map(lambda a:(float(a[0]),a[1])).collectAsMap()  
len(movieTitle)


以上结果显示“电影ID与名称“字典共计1682项。

image

针对用户100推荐5部可能感兴趣的电影

1
2
3
recommendP = model.recommendProducts(100,5)  
for p in recommendP:
print("对用户:"+str(p[0])+",推荐电影:"+str(movieTitle[p[1]])+",推荐评分:"+str(p[2]))

参考网站: 章鱼大数据

CATALOG
  1. 1. 相关知识
  2. 2. 系统环境
  3. 3. 任务步骤
    1. 3.1. 前期准备
    2. 3.2. 代码调试
      1. 3.2.1. 我们使用sc.textFile读取ml-100k
      2. 3.2.2. 查看u.data第一项数据
      3. 3.2.3. 导入Rating模块
      4. 3.2.4. 读取rawUserData前三个字段,按照用户、产品、用户对此产品的评价来编写rawRatings
    3. 3.3. 准备ALS训练数据
      1. 3.3.1. 使用下列命令编写ratingsRDD
      2. 3.3.2. 查看不重复用户数
      3. 3.3.3. 查看不重复电影数
      4. 3.3.4. 如何训练模型
      5. 3.3.5. 导入ALS模块
      6. 3.3.6. 使用ALS.train介绍
        1. 3.3.6.1. 显式评分(Explicit Rating)训练
      7. 3.3.7. 如何使用模型进行推荐
      8. 3.3.8. 针对用户推荐电影
      9. 3.3.9. 查看针对用户推荐产品的评分
      10. 3.3.10. 显示推荐的电影名称
      11. 3.3.11. 为了显式推荐电影的名称,我们创建“电影ID与名称”的字典
      12. 3.3.12. 针对用户100推荐5部可能感兴趣的电影