相关知识
推荐引擎是最常见的机器学习应用,我们可以在各大购物网站上看见这方面的应用。
Spark MLlib支持ALS(Alternating Least Squares)推荐算法,是机器学习的协同过滤推荐算法。机器学习的协同过滤推荐算法通过观察所有用户给产品的评价来推断每个用户的喜好,并向每个用户分别推荐多个合适的产品,也可以把某个产品推荐给多个用户。
系统环境
Linux Centos7
Python 3.7.3
Anaconda
Spark2.4.2
IPython Notebook
任务步骤
前期准备
- 将hadoop相关服务打开
在hadoop/sbin目录下./start-all.sh
- 启动mysql服务
- 将文件上传到hdfs中
命令:hadoop fs -put /ml-100k(ml-100k的目录) /
- 开启PySpark
代码调试
我们使用sc.textFile读取ml-100k
我们使用sc.textFile读取HDFS上的ml-100k数据集中的u.data,并且查看数据项数
1 | rawUserData = sc.textFile("hdfs://172.18.74.236:9000/ml-100k/u.data") |
从以上运行结果中可以看到共有100000项评分数据。
查看u.data第一项数据
1 | rawUserData.first() |
以上4个字段分别是:用户id、项目id、评分、日期时间,\t为分隔符。
导入Rating模块
1 | from pyspark.mllib.recommendation import Rating |
读取rawUserData前三个字段,按照用户、产品、用户对此产品的评价来编写rawRatings
1 | rawRatings = rawUserData.map(lambda line:line.split("\t")[:3]) |
以上程序显示了前5项rawRatings数据。上列命令的详细说明如下:
准备ALS训练数据
ALS训练数据格式是RatingRDD数据类型,Rating定义如下:
使用下列命令编写ratingsRDD
1 | ratingsRDD = rawRatings.map(lambda x:(x[0],x[1],x[2])) |
以上运行结果显示共有100000项评价
查看不重复用户数
x[0]是用户字段,可以先用.map(lambdax:x[0])
转换为用户数据,再使用.distinct()
筛选出不重复的数据,最后显示numUsers
1 | numUsers = ratingsRDD.map(lambda x:x[0]).distinct().count() |
以上运行结果显示共有943个不重复用户
查看不重复电影数
x[1]是电影字段,可以先使用.map(lambda x:x[1])
转换为电影数据,再使用.distinct()筛选出不重复的数据
1 | numMovies = ratingsRDD.map(lambda x:x[1]).distinct().count() |
如何训练模型
如图,我们将使用rawUserData数据以map转换为rawRatings,再改用map转换为ALS训练数据格式RDD[Rating]。然后使用ALS.train进行训练,训练完后就会创建推荐引擎模型MatrixFactorizationModel。
导入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
两种评分训练的作用都是训练数据并返回模型
我们可以使用ALS.train命令并传入之前创建的ratingsRDD进行训练,训练完成后返回model
1 | model = ALS.train(ratingsRDD,10,10,0.01) |
如何使用模型进行推荐
前面我们已经训练完成并建立了模型,接下来将使用此模型进行推荐
针对用户推荐电影
我们可以针对每个会员定期发送消息,或在会员登录时向会员推送可能会感兴趣的电影。
针对用户推荐电影,我们可以使用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) |
参数说明:
使用训练完的模型,推荐对电影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 | itemRDD = sc.textFile("hdfs://172.18.74.236:9000/ml-100k/u.item") |
为了显式推荐电影的名称,我们创建“电影ID与名称”的字典
1 | movieTitle=itemRDD.map(lambda line:line.split("|")).map(lambda a:(float(a[0]),a[1])).collectAsMap() |
以上结果显示“电影ID与名称“字典共计1682项。
针对用户100推荐5部可能感兴趣的电影
1 | recommendP = model.recommendProducts(100,5) |
参考网站: 章鱼大数据