本节将会学习到:
协同过滤推荐系统
协同过滤推荐系统的R实现
推荐系统的可视化
不同推荐系统的离线实验算法比较及可视化
前言
本节我们来探讨和学习下推荐系统的相关内容。随着大数据时代的到来,我们越来越感受到数据无处不在。我们已经处于一个数据过载的环境,无论是电商网站眼花缭乱的物品,还是纷繁复杂的社交网络,以往通过熟人推荐或者有限选择的旧模式已经无法满足自身的需求。如是乎推荐系统,或称协同过滤推荐(Collaborative Filtering recommendation ) 如火如荼发展起来。
推荐系统的任务就是联系用户和信息,一方面帮助用户发现对自己有价值的信息,另一方面让信息能够展现在对它感兴趣的用户面前,从而实现信息消费者和信息生产者的双赢。无论是针对推荐系统中的数据稀疏及冷启动问题,还是在大数据条件下是实现,推荐系统已经形成自己专门的研究体系。本文只是个人最近处于入门的学习中的一些总结,无论从知识体系,还是问题的理解深度都还有很大差距,但是作为自我学习的记录和分享,还是决定写出来,接受各位的拍砖。
推荐系统概述
想象下对于一个拥有数量庞大图书的图书馆,想从中尽快的挑选到自己满意的某一本书,我们应该怎么做?可能我们主要有以下4种做法:首先可能是从过往的经验中寻找。从自己熟悉的某个栏目,或者之前看过类似的书籍附近的栏目中寻找;二是询问自己的“熟人”或看过类似书籍的人。从他们那里获得想要找的书在哪里找到;第三应该是找到图书馆目录表,从不同分类目录中寻找;当然最后一种应该是先从图书馆搜索引擎中输入书籍信息,找到书的位置。其实这也是解决信息过载(图书数量巨大)问题主要的方法:基于物品或用户的协同过滤推荐、分类目录和搜索引擎方法。当然这些解决方案分别催生了互联网领域的几大著名公司——亚马逊、雅虎和谷歌。但分类目录及搜索引擎对于用户无法准确描述自己需求时(无法描述具体希望看某一本书时),往往无能为力。而推荐系统能够在用户没有明确目的的时候帮助他们发现感兴趣的新内容。
评价推荐系统的实验方法主要有3种:离线实验(offline experiment)、用户调查(user study)和在线实验(online experiment)。
离线实验主要针对已有数据集,按一定规则分成训练集和测试集,通过预测准确度、覆盖率等评价模型好坏;用户调查即通过传统的调查问卷方式获得用户基本信息及对推荐结果的主观感受等,可额外获得客户满意度、新颖性、惊喜度等评价效果;在线实验主要用于在离线及用户调查结果良好,将推荐系统上线做AB测试,评价算法的性能。主要评价指标如点击率、信任度、实时性、健壮性及商业目标的达成等。
推荐系统的形式主要有2种:Top-N推荐和推荐评分(或0-1评分)。这也是我们日常在浏览网页或电影、歌曲中最常见的推荐形式。
协调过滤算法又主要有:基于邻域算法(包含基于用户的协同过滤(item-based CF)及基于物品的协同过滤(user-based CF))、 隐语义模型及基于图的随机游走算法等。而应用于商业最多的属基于邻域的算法。开源的推荐系统非常多,基本上都是用C++/Java实现,即有轻量级的适用于做研究的SVDFeature、LibMF、LibFM等,也有重量级的适用于工业系统的Mahout、Oryx、EasyRecd等。基于Python的主要有Crab(Python)和Python-recsys(Python),基于R的主要有Recommenderlab(R)。详情可参考[推荐系统开源软件列表汇总和点评]<http://blog.csdn.net/cserchen/article/details/14231153#tc_qz_original=691102124>。
至于如何选择合适的推荐模型,下面这张图我个人觉得是非常实用的,推荐参考[选择合适的推荐系统模型]<http://blog.jobbole.com/86959/>。
关于推进系统的数据也非常多,目前本人只看了入门级书籍:《推荐系统实践》和《集体智慧编程》(均用Python编程),可在知乎中自行搜索。作为一名R爱好者,个人认为先搞清楚R在推荐系统中的使用是基础,因此下面将通过recommenderlab包,介绍推荐系统的相关内容。
数据构成
set.seed(1234)
library("recommenderlab")
m <- matrix(sample(c(as.numeric(0:5), NA), 50,
replace=TRUE, prob=c(rep(.4/6,6),.6)), ncol=10,dimnames=list(user=paste("u", 1:5, sep=''), item=paste("i", 1:10, sep='')))
r <- as(m,"realRatingMatrix")m;r
## item
## user i1 i2 i3 i4 i5 i6 i7 i8 i9 i10
## u1 NA 2 3 5 NA 5 NA 4 NA NA
## u2 2 NA NA NA NA NA NA NA 2 3
## u3 2 NA NA NA NA 1 NA NA NA NA
## u4 2 2 1 NA NA 5 NA 0 2 NA
## u5 5 NA NA NA NA NA NA 5 NA 4
## 5 x 10 rating matrix of class 'realRatingMatrix' with 19 ratings.
运用recommenderlab包实现协同过滤推荐,其数据类型采用S4类构造,使用抽象的raringMatrix为评分数据提供接口。先自行构建一个包含缺失值的矩阵,行为u1-u5个用户,列为i1-i10的物品。需通过as()函数转为raringMatrix类型。raringMatrix采用了很多类似矩阵对象的操作,如dim(),dimnames(),rowCounts(),colMeans(),rowMeans(),colSums(),rowMeans();也增加了一些特别的操作方法,如sample(),用于从用户(即,行)中抽样,image()可以生成像素图。
数据转换
head(as(r,"data.frame"))
## user item rating
## 5 u1 i2 2
## 7 u1 i3 3
## 9 u1 i4 5
## 10 u1 i6 5
## 13 u1 i8 4
## 1 u2 i1 2
n <- normalize(r)
image(r,main = "Raw rating")
image(n,main = "normalized rating")
#二元分类转换
r_b <- binarize(r,minRating = 4)
b <- as(r_b,"matrix")b
## i1 i2 i3 i4 i5 i6 i7 i8 i9 i10
## u1 0 0 0 1 0 1 0 1 0 0
## u2 0 0 0 0 0 0 0 0 0 0
## u3 0 0 0 0 0 0 0 0 0 0
## u4 0 0 0 0 0 1 0 0 0 0
## u5 1 0 0 0 0 0 0 1 0 1
数据也可转换为数据框类型,或通过normalize()函数进行标准化处理,标准化的目的是为了去除用户评分的偏差;通过binarize()函数转为binaryRatingMatrix类型,适用于是0-1的评分矩阵(赞/踩)。
数据可视化
为更好说明推荐系统的算法,我们采用非常出名的MovieLense数据集,其收集了网站MovieLens(movielens.umn.edu)从1997年9月19日到1998年4月22日的数据,包括943名用户对1664部电影的评分。getRatings()函数可获取评价数据。image()可查看数据分布。
data(MovieLense)
r <- sample(MovieLense,943,replace = F)
image(MovieLense)
hist(getRatings(normalize(MovieLense)),breaks = 100)
hist(rowCounts(r),breaks = 50)
创建推荐
查看推荐方法
我们已经获得了评分数据,现在来看看recommenderlab包可以实现哪些推荐算法呢!可以运用recommenderRegistry$get_entry_names()函数实现。参数realRatingMatrix表示数据类型是推荐评分型(如1-5颗星评价),可具体查看算法说明。对于realRatingMatrix有六种方法:IBCF(基于物品的推荐)、UBCF(基于用户的推荐)、SVD(矩阵因子化)、PCA(主成分分析)、 RANDOM(随机推荐)、POPULAR(基于流行度的推荐)。
recommenderRegistry$get_entry_names()
## [1] "AR_binaryRatingMatrix" "IBCF_binaryRatingMatrix"
## [3] "IBCF_realRatingMatrix" "PCA_realRatingMatrix"
## [5] "POPULAR_binaryRatingMatrix" "POPULAR_realRatingMatrix"
## [7] "RANDOM_realRatingMatrix" "RANDOM_binaryRatingMatrix"
## [9] "SVD_realRatingMatrix" "SVD_binaryRatingMatrix"
## [11] "UBCF_binaryRatingMatrix" "UBCF_realRatingMatrix"
recommenderRegistry$get_entries(dataType = "realRatingMatrix")
建立模型
建立协同过滤推荐算法模型,主要运用Recommender(data=ratingMatrix,method,parameter=NULL)函数,getModel()可查看模型参数。
r_recom <- Recommender(r,method = "IBCF")
r_popul <- Recommender(r,method = "POPULAR")
#查看模型方法
names(getModel(r_recom))
## [1] "description" "sim" "k"
## [4] "method" "normalize" "normalize_sim_matrix"
## [7] "alpha" "na_as_zero" "minRating"
## [10] "verbose"
模型预测
TOP-N预测
对模型预测可运用predict()函数,在此分别以TOP-N预测及评分预测为例,预测第940-943位观影者的评分情况。n表示最终为TOP-N的列表推荐,参数type = "ratings"表示运用评分预测观影者对电影评分,模型结果均需转为list或矩阵表示。
pred <- predict(r_popul,r[940:943],n= 5)as(pred,"list")
#top-N为有序列表,抽取最优推荐子集
pred3 <- bestN(pred,n = 3)
as(pred3,"list")
#评分预测
rate <- predict(r_popul,r[940:943],type = "ratings")
as(rate,"matrix")[,1:5]
预测模型评价
评分预测模型评价
建立推荐系统模型后,非常关心的是对预测模型的评价。可通过evaluationScheme()将数据按一定规则分为训练集和测试集(参数method = "split",),或进行k-fold交叉验证(如method = "cross",k=4),given参数表示用来进行模型评价的items的数量。分别运用UBCF及IBCF算法,进行预测评价。
getData(e,"train")表示获取训练集数据,predict(r1,getData(e,"known"),type = "ratings")表示对“已知”训练集数据进行预测。计算预测模型的准确度可通过calcPredictionAccuracy()函数实现,参数“unknown”表示对“未知”test集进行比较。结果发现两种方法的均方根误差(RMSE)基本一致。
e <- evaluationScheme(r[1:800],method = "split",train = 0.9,given = 15,goodRating = 5);e
## Evaluation scheme with 15 items given
## Method: 'split' with 1 run(s).
## Training set proportion: 0.900
## Good ratings: >=5.000000
## Data set: 800 x 1664 rating matrix of class 'realRatingMatrix' with 83043 ratings.
r1 <- Recommender(getData(e,"train"),"UBCF");
p1 <- predict(r1,getData(e,"known"),type = "ratings");
r2 <- Recommender(getData(e,"train"),"IBCF");
p2 <- predict(r2,getData(e,"known"),type = "ratings");
##计算预测模型的准确度
c1 <- calcPredictionAccuracy(p1,getData(e,"unknown"))
c2 <- calcPredictionAccuracy(p2,getData(e,"unknown"))
error <- rbind(c1,c2)rownames(error) <- c("UBCF","IBCF")
error
## RMSE MSE MAE
## UBCF 1.053345 1.109537 0.8338755
## IBCF 1.172571 1.374924 0.8580037
TOP-N预测模型评价
让我们来评价TOP-1,TOP-3,TOP-5,TOP-10推荐准确性。通过4-fold交叉验证方法分割数据集,运用evaluate()进行TOP-N预测模型评价。评价结果可通过ROC曲线及准确率-召回率曲线展示。
#4-fold交叉验证
tops <- evaluationScheme(r[1:800],method = "cross",k = 4,given = 3, goodRating = 5)
tops
## Evaluation scheme with 3 items given
## Method: 'cross-validation' with 4 run(s).
## Good ratings: >=5.000000
## Data set: 800 x 1664 rating matrix of class 'realRatingMatrix' with 83043 ratings.
results <- evaluate(tops,method = "POPULAR",type = "topNList", n = c(1,3,5,10))
## POPULAR run fold/sample [model time/prediction time]
## 1 [0.02sec/0.16sec]
## 2 [0.02sec/0.17sec]
## 3 [0sec/0.14sec]
## 4 [0.02sec/0.16sec]
#获得混淆矩阵
getConfusionMatrix(results)[[1]]
avg(results)
#ROC曲线
plot(results,annotate = TRUE)
#准确率-召回率曲线
plot(results,"prec/rec",annotate = TRUE)
推荐算法的比较
除了对预测模型进行评价,还可以对不同推荐算法进行比较。可首先构建一个推荐算法列表,通过ROC曲线、准确率-召回率曲线或RMSE直方图进行比较。
TOP-N算法比较
set.seed(2016)
scheme <- evaluationScheme(r,method = "split",train = 0.9,k= 1,given = 10,goodRating = 5)
#构建推荐算法列表
algorithms <- list(
"random items" = list(name="RANDOM", param=NULL), "popular items" = list(name="POPULAR", param = list(normalize = "Z-score")), "user-based CF" = list(name="UBCF", param = list(normalize = "Z-score", method = "Cosine", nn = 25, minRating = 3)), "item-based CF" = list(name="IBCF", param=list(k=50)), "SVD approximation" = list(name="SVD", param=list(approxRank = 50)))
#构建不同算法模型
results <- evaluate(scheme, algorithms, n = c(1, 3, 5, 10, 15, 20))
#模型比较#ROC曲线
plot(results,annotate = c(1,3),legend = "bottomright")
#准确率-召回率曲线
plot(results,"prec/rec",annotate = c(2,3,4),legend = "topleft")
预测评分算法比较
results2 <- evaluate(scheme,algorithms,type = "ratings")
plot(results2,ylim = c(0,20))
应用新的推荐算法
当然在recommenderlab包说明文档中也有自定义新的推荐算法的举例,通过编辑推荐算法的函数实现符合实际的推荐算法。但要说明的是运用R进行协同过滤推荐并不是推荐系统应用的主流,主要原因在于算法调整不灵活,并且R主要依靠内存的单线程计算,并不太适用于过大规模的推荐应用。
参考资料
[推荐系统开源软件列表汇总和点评]http://blog.csdn.net/cserchen/article/details/14231153#tc_qz_original=691102124
[选择合适的推荐系统模型]http://blog.jobbole.com/86959/
项亮编著的《推荐系统实践》
《集体智慧编程》
recommenderlab 说明文档
豆瓣:数据铺子,recommenderlab:构建基于R的推荐系统
刘 可,推荐系统简介及其R语言实现 通信与信息技术201 年第1期
其他推荐系统资料
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。