协同过滤(Collaborative Filtering),简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐使用者感兴趣的信息,个人透过合作的机制给予信息相当程度的反馈(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,反馈不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要,比如浏览信息,收藏,分享,点击等。
在前一篇文章 使用Spark MLlib给豆瓣用户推荐电影 中,在那篇文章我我介绍了使用Spark MLlib实现了model-based 的系统过滤之推荐系统。但是Spark并没有提供user-based, item-based这两种memory-based传统的协同过滤算法,所以接下来的这两篇文章我会介绍使用Mahout实现user-based和item-based的电影推荐系统,数据还是基于豆瓣用户对电影的评论数据集。
Mahout是Apache的实现大规模的高性能的机器学习框架。它提供了很多的机器学习的算法和工具,以及利用Hadoop实现分布式的计算,本文将使用它的协同过滤算法(CF)实现非分布式的单机程序。
user-based协同过滤推荐算法就是通过不同用户对item的评分来评测用户之间的相似性,基于用户之间的相似性做出推荐。
下一篇文章中介绍item-based协同过滤推荐算法是通过用户对不同item的评分来评测item之间的相似性,基于item之间的相似性做出推荐。
User-based 优点:
- 能够过滤机器难以自动内容分析的信息,如艺术品,音乐等。
- 共用其他人的经验,避免了内容分析的不完全或不精确,并且能够基于一些复杂的,难以表述的概念(如信息质量、个人品味)进行过滤。
- 有推荐新信息的能力。可以发现内容上完全不相似的信息,使用者对推荐信息的内容事先是预料不到的。可以发现使用者潜在的但自己尚未发现的兴趣偏好。
- 推荐个性化、自动化程度高。能够有效的利用其他相似使用者的反馈信息。加快个性化学习的速度。
缺点
- 新使用者问题(New User Problem) 系统开始时推荐质量较差
- 新项目问题(New Item Problem) 质量取决于历史资料集
- 稀疏性问题(Sparsity)
- 系统延伸性问题(Scalability)。
下面根据代码介绍具体的实现:
|
|
上面一段代码是生成电影ID和名称的字典,这个文件的每一行代表一条热门电影,如20645098,8.2,小王子
。这样在我们输出结果的时候,可以方便的查看电影名,因为电影名比ID更有意义。
|
|
第6行读入数据模型,因为我们的数据文件中用户的id是字符串类型的,我们需要将它转换成一个Long类型的数据,所以实现了一个定制的类DoubanFileDataModel
。
第8行我们使用PearsonCorrelationSimilarity
计算相似度,Mahout还提供了其它的计算相似度的算法:
|
|
第10生成UserBased Recommender类。
第13行到第22行我们为前100个用户生成推荐结果,并输出到终端窗口,这样我们可以先检查一下推荐的结果。
因为矩阵是很稀疏的,这种user-based算法可能没有提供给用户推荐的电影,有的用户可能不到5个推荐电影。
这段代码剩下的部分就是把所有的用户推荐结果都输出到一个文件中。
DoubanFileDataModel
类的实现如下:
|
|
下面是推荐结果的片段:
|
|
user-based CF算法适用于:
- 用户较少的场合,否则用户相似度矩阵计算代价很大
- 适合时效性较强,用户个性化兴趣不太明显的领域
- 对新用户不友好,对新物品友好,因为用户相似度矩阵不能实时计算
- 很难提供令用户信服的推荐解释
item-based CF算法适用于:
- 物品数明显小于用户数的场合,否则物品相似度矩阵计算代价很大
- 适合长尾物品丰富,用户个性化需求强的领域
- 对新用户友好,对新物品不友好,因为物品相似度矩阵不需要很强的实时性
- 利用用户历史行为做推荐解释,比较令用户信服
推荐阅读项亮的推荐系统实践,了解推荐系统的基础知识。
代码下载: github