基于Spark ALS算法的个性化推荐(仅需三行代码)

浏览: 2113

今天来使用spark中的ALS算法做一个小推荐。需要数据的话可以点击查看初识sparklyr—电影数据分析,在文末点击阅读原文即可获取。

其实在R中还有一个包可以做推荐,那就是recommenderlab。如果数据量不大的时候可以使用recommenderlab包,之前也用该包做过电影评分预测模型(点击即可查看)。如果数据量较大还是推荐使用spark来进行计算。

在spark中包含了许多机器学习算法,其中就有一个推荐算法,即ALS。

ALS是最小二乘法(alternating least squares)的简写,它是一种求解矩阵分解问题的最优化方法。何为矩阵分解?就是把一个评分矩阵A分解为两个矩阵B,C。B*C=A。为什么要进行分解?那是因为矩阵A是一个稀疏矩阵,分解之后的B,C矩阵相对能稠密一点,可以实现降维。另外,当建立模型之后,也比较容易求出推荐结果。使用该算法可以很方便的做一个推荐系统,核心代码只有三行。

一.读取数据

数据可以在初识sparklyr—电影数据分析文末点击阅读原文即可获取。

moviedata<-read.table("u.data",header = FALSE,sep = "\t")

#这四列数据分别表示:用户id,电影id,评分,时间戳
head(moviedata)#
V1 V2 V3 V4
1 196 242 3 881250949
2 186 302 3 891717742
3 22 377 1 878887116
4 244 51 2 880606923
5 166 346 1 886397596
6 298 474 4 884182806
# 删除第四列
moviedata<-moviedata[,-4]
#重命名列
colnames(moviedata)<-c("userid","itemid","rating")

连接到spark

library(sparklyr)
library(dplyr)
sc <- spark_connect(master = "local")

二. 推荐

前面那些都是准备工作,现在就来实现推荐部分,真的只需三行代码。

#1 保存到spark中
moviedataSpark<-copy_to(sc,moviedata,overwrite = TRUE )
#2 建立模型
moviedata_model<-ml_als_factorization(moviedataSpark,rating_col="rating",
user_col="userid",item_col="itemid")
summary(moviedata_model)#此句是查看模型属性#每个用户推荐2个
#3 生成推荐结果
movie_recommend<-ml_recommend(moviedata_model,type = c("items"),n=2)
> movie_recommend
# Source: table<sparklyr_tmp_9fd405a6463> [?? x 4]# Database: spark_connection
userid recommendations itemid rating
<int> <list> <int> <dbl>
1 12 <list [2]> 1450 5.32
2 12 <list [2]> 113 5.17
3 13 <list [2]> 1643 5.59
4 13 <list [2]> 814 4.87
5 14 <list [2]> 1367 5.18
6 14 <list [2]> 1463 5.17
7 18 <list [2]> 1449 4.86
8 18 <list [2]> 1642 4.78
9 25 <list [2]> 1643 4.80
10 25 <list [2]> 1449 4.70
# ... with more rows

是不是三句代码就搞定了。没骗人吧。从结果可以看到给用户id为12的用户推荐的是1450和113.在这里ALS算法其他参数给的都是默认值,可以通过不断调整参数来优化我们的模型。

三.模型评估

模型生成之后需要对模型进行评估,我们可以使用RMSE方法进行模型计算评估,它的计算公式如下:

不过要在之前我们需要知道用户对电影的预测评分,然后根据预测评分和实际评分来计算出RMSE结果。获取预测评分可以使用transform方法,如果你想要更多的了解transform方法,可以打开:http://spark.apache.org/docs/latest/ml-collaborative-filtering.html进行查看官方文档说明。

#评分预测
#invoke用于调用java对象方法
movie_prediction<-moviedata_model$.jobj%>%invoke("transform",spark_dataframe(moviedataSpark))%>%collect()
> movie_prediction
#预测结果
# A tibble: 100,000 x 4
userid itemid rating prediction
<int> <int> <int> <dbl> 1 13 12 5 3.83
2 14 12 5 4.47
3 18 12 5 4.21
4 73 12 5 4.28
5 109 12 4 3.70
6 110 12 4 3.40
7 115 12 5 4.57
8 130 12 4 4.85
9 135 12 4 4.21
10 177 12 5 4.32
# ... with 99,990 more rows#模型评估

model_RMSE<-sqrt(mean((movie_prediction$rating-movie_prediction$prediction)^2))

在计算模型时,参数给的都是默认值,此时model_RMSE=0.7725977。该值越小,说明该模型越好。

现在修改参数,当把参数调整为:reg_param=0.05,max_iter = 20L,alpha=2

model_RMSE等于0.7123907.比默认时的值小了0.06,就这样通过不断优化调整参数来使得模型最优。




☞ 推荐阅读

1:用 = 还是<-?傻傻分不清

2:Windows系统是这样配置spark环境的

3:被自己吓到了,估计这样写爬虫的也就只有我一个人

4:啤酒和尿布的故事是真的吗

5:初识sparklyr—电影数据分析

6:基于R语言构建的电影评分预测模型


推荐 1
本文由 王亨 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册