Mahout--(五)mahout疑问解答

来源:http://www.douban.com/note/245740667/

 提问1:

博涛前辈,您好!打扰您了,我想请教您一些问题。我是一名在读研一学生,研究推荐系统方面的知识。 我一直很困惑,在实际应用中,给定一个应用系统,例如淘宝,或者给定一个应用系统积累的数据集,如何用推荐系统的思想着手分析,如何为系统设计一个好的推荐方法,又是怎样一个流程去分析这类问题?我看了mahout in action书中recommendations章节chapter 5提到对于一个数据集的分析思路,先选择effective recommender,再结合领域知识过滤推荐,再继续分析解决新用户和新对象问题等。我不确定现实应用中是不是也是这样分析的?还有对于推荐系统领域的一些疑难杂症,在现实应用中是不是都能通过一些办法解决?比如新用户问题,借助用户的注册信息或者访问cookie(您对另一位读者的回答中提到)解决,对于新对象问题,则借助content-based方法解决? 最后对于我自己目前的状况我很疑惑,即作为一个学生,研究推荐系统知识,应该把重点放在算法改进研究上,还是对实际问题的分析解决上?我觉得学术研究和实际应用还是有一定的区别的,而且我看了这块领域中的一些算法改进的论文,我觉得拿到现实中未必有用。不好意思,提了这么多问题,希望前辈能为我解惑!


回答:

我概括了下你的回复里面有三个问题。1. 如何为一个有数据积累的应用系统设计和构建一个推荐系统?2. 如何解决冷启动问题?3. 对于刚了解推荐系统的同学的一些建议?这三个问题如果展开叙述,都可以写好几篇博文了,所以在这里,我只是简要的回答你,可能会有不完全的地方:) 

原 Google 研究员张栋(@张栋_机器学习)对于推荐系统影响因素概括了 5 点,即:产品设计:30%,数据:30%,领域知识:20%,算法:10%,工程优化:10%。我觉得张栋老师概括的非常好,从中可以看到数据对于推荐系统的重要性。如果你有一个将要构建推荐系统的应用,数据只是一个必备的前提,要真正实践一个推荐系统,首先还是得从用户的需求出发,根据用户的需求明确推荐系统提供哪一些服务,所提供的这些服务想达到什么样的目标,即:做什么?目标是什么?。比如,新浪微博在 09 年刚上线的时候肯定也面临着如何构建推荐系统的问题,可以肯定的是经过他们的一番思考后,他们抓住了用户的两点需求:(1)热门话题和新闻通常会得到大家的高度关注;(2)好友之间的互动。他们的目标也很简单(1)提高用户的发微、转发、评论的频率,增加用户对微博的黏性;(2)构建新浪微博的好友生态圈。大家现在去看看新浪微博,他们的推荐形式几乎就这两种,没怎么大变,但是效果确实越来越好,因为他们不断的再实践和优化。 

知道了做什么和目标,下面我们就讨论下怎么做。一般来说构建推荐系统基本流程是:用户行为、数据分析建模 -> 推荐算法设计和相关性计算 -> 生成推荐结果(含推荐解释) 

1. 用户行为、数据分析建模 
如果你的数据分布在访问日志和数据库的多个表中(例如订单表、收藏记录表、评价表、订阅表),那么一般需要把这些数据提取出来,并转换成用户的行为数据 user_behavior(user_id, item_id, behavior_type, behavior_content, behavior_weight)。用户的行为数据来源非常广,对于一个电子商务网站而言,购买、浏览、收藏、评价、订阅等隐性行为,用户问卷调查等显性行为贡献了大量的数据。另一方面,注册信息也是用户的重要特征数据。 

2. 推荐算法设计和相关性计算 
相关性计算(也就是相似性计算)和推荐算法是密切联系的,根据推荐算法的不同,我们需要计算用户之间的相似性和物品之间的相似性。而用户之间的相似性可以是行为的相似性,也可以是用户属性(年龄、性别、地域)的相似性。物品之间的相似性可以是基于用户反馈的相似性,也可以是物品内容的相似性。 

推荐算法包括 UserCF、ItemCF、Content-based、Demographic-based 等,应该说这些算法都各有优点和缺点,在应用中也会根据实际情况选择其中的一种或多种方法。通常,我们能够根据经验排除某几种或选择某几种。例如:微博的好友推荐主要使用的推荐算法是 UserCF 和 Hot-based,如果你已经使用微博一段时间,微博会根据你关注的用户生成你的好友圈子推荐给你;如果你关注的用户很少,比如新用户,那么会推荐那些大 V 用户给你,比如姚晨啊、开复老师啊。另外一个典型的例子,就是 Amazon,我们知道 ItemCF 是 Amazon 提出来的,在这之前 UserCF 已经用了好几年,但是 Amazon 的工程师在推荐系统的实践中觉得 UserCF 不适合他们,因为:(1)用户的数量远大于商品的数量,同时用户的增长规模也大于商品的增长规模,所以 UserCF 的计算量会越来越大;(2)用户的相似性是不稳定的,而商品的相似性却要稳定的多,《Thinking in Java》和《Effective Java》是相似的两本书,它们今天相似,过一个月后,过一年之后都是相似的,但两个用户 A 和 B,他们今天喜欢同样的书籍,我们认为他们是相似的,但过了一天或一周后可能他们喜欢的书籍会发生很大的变化导致他们不再相似,所这就要求 UserCF 要进行频繁的计算;(3)UserCF 难以生成让人信服的推荐理由,你买个东西告诉你是因为你和某某人相似,而你却连这某某人是谁都不知道。正因为这些原因 Amazon 的工程师提出了 ItemCF 算法。 

相似性计算的方法有很多,余弦相似性、欧氏距离、皮尔森相关系数、内容相似性 等等,可以参看我之前的 blog http://blog.csdn.net/bornhe/article/details/7425642。 

最终选取哪一种推荐算法和哪一种相似性,取决于评测的结果。通常,我们会实验每一种方法,然后选择最优的一种,这里使用了机器学习里面的监督学习方法,可以看我之前的回复http://www.douban.com/note/208193209/#30908428。 

说那么多,还了举微博和 Amazon 的例子,主要是为了说明推荐算法是一种领域性很强的算法(你问题里也提到了领域),别的系统用的很好的推荐算法,放到你的系统里不一定会表现很好,所以我们需要进行领域分析和推荐算法的评测,评测的方法有 RMSE(Netflix 用的离线评测指标)、precision、recall,这在 《Mahout in Action》Part 5 里面也有详细的介绍。 

3. 生成推荐结果(含推荐解释) 
前两步的计算量非常大,一般都是离线完成。而生成推荐结果却是实时的,用户请求来,我们就匹配和用户最相关的物品推荐给用户,这一步我会进行结果的过滤、排序和推荐结果的解释。过滤处理很简单,就是把用户已经产生过行为的物品、质量差的物品过滤掉。而排序则要复杂的多,需要考虑推荐物品的相关性、新颖性、多样性和时间上下文等多种因素,一个个性化的推荐系统,排序也要是个性化的,这意味着我们需要为每一个用户(或每一个群体)训练一个排序模型,训练的过程也是离线完成的,关于推荐系统的排序可以参考我翻译的 Netflix 推荐系统的 blog:http://blog.csdn.net/bornhe/article/details/8222497。最后,推荐解释也是很重要的,我们需要说清楚推荐结果是来源于用户的那些行为或属性,好的推荐解释能够增加用户对推荐结果的信任度,这样用户会更可能购买或评价。 

补充一点:关于推荐算法的评测,离线评测是其中重要的一种,通常在实际场景中还会安排线上评测,也就是 A/B 测试,我们会把好几种通过离线评测的算法和模型放到线上去经受用户的考验,最终挑出最优的几种。关于 A/B 测试,也可以参看 http://blog.csdn.net/bornhe/article/details/8222497的后面部分。 

PS:有很多 blog 在讨论 #推荐系统构建# 这个话题的时候,都是围绕着怎么做开始的,从中你可以看到业界很多公司使用的都不是单独的一种推荐算法,而是一种混合的推荐算法,但是细节一般都秘而不宣。 

------------------------------------------------------------------------ 
对于你的第二个问题:如何解决冷启动? 

其实在你的问题里面已经有了答案。也就是对于新用户,我们可以使用 Demographic-based 和 Hot-based(排行榜)来解决冷启动问题;对于新物品,可以用 Content-based 来解决冷启动问题。在这里 http://www.douban.com/note/204399134/#30943588 有我之前具体的回复。 

------------------------------------------------------------------------ 
对于你的第三个问题:对于刚了解推荐系统的同学的一些建议? 

其实我也刚走出校园一年多,之前在学校的时候也有类似于你的困惑。有一点,我觉得要明确:不管是在学校,还是去企业里面实习,都很难有“实际问题分析解决”的机会,所以在学校可以多利用自己的业余时间开阔自己的视野,可以多关注一些大牛和知名公司的技术博客 
Gren Linden(ItemCF 算法的提出者之一) blog:http://glinden.blogspot.com/ 
项亮大牛的 blog:http://xlvector.net/blog/ 
谷文栋大牛的 blog:http://www.guwendong.com/archives 
阿稳大牛的 blog:http://www.wentrue.net/blog/ 
Netflix 技术 blog:http://techblog.netflix.com/ 
项亮和谷文栋一起发起了 Resys China http://www.resyschina.com/,项亮的《推荐系统实践一书》也相当推荐阅读,在第 7 章——推荐系统实例,相信能给你对于 #推荐系统构建# 更多的答案。 

另外也有很多的实践机会,网上有很多的真实可用数据可以供我们使用,《Mahout in Action》中介绍的 GroupLen 就是很好的资源(而且这些数据都是经过提取和转化处理的),用这些数据,结合自己的学习,不断的实践,相信能够取得不小的进步。如果身边有同兴趣的同学,你们还可以一起组队参加 Netflix Prize 推荐系统大赛,项亮曾在 09 年参加过 Netflix Prize,并取得了第二名的好成绩,详见:http://www.netflixprize.com/leaderboard,这些都是很好的实践的机会。 

总之,多读论文多实践,眼光长远,相信你一定取得好成绩。



提问2:

博涛,真的很感激你为我认真耐心地解答疑惑,解答不仅内容详细、调理很清楚,更是切中了困惑我很久的问题!我认真研究了你写的每一个字,对链接也进行了深入的阅读,并做了笔记,似乎我之前脑海中的一片糊涂开始变得清晰了,很多知识我可能也知道,但是我没有整体概念,对于细节和深入的本质更是模糊不清。有时候模糊的连自己的问题在哪里都不知道,更别提查找资料解决问题了。看了你的回答,我思路更清晰了,同时我也更明确作为一个在校学生,应该做什么了!很多时候我知道自己有很多可以选择的路,但是因为没有过来人的指点,总担心自己会迂回绕远,这也许是很多走在路上的人的困惑吧。另外,我还得打扰你一下,我整理知识过程中,发现我还有几点不是很明白:(1)线下计算大概是怎样实现的?是将各种相似性矩阵结果提前计算好,存储在文件系统或数据库系统中,然后线上推荐时对相关信息进行读取再计算推荐?(2)训练集和测试集问题。《mahout in action》书中进行评测时是通过一个比例参数决定百分之多少为训练集,剩余的百分之多少为测试集,groupLens的100k的数据集中有ua.base 和ua.test两个数据文件,ua.base应该是用作训练,ua.test应该是用作测试的(我看着应该是的),在评测时我怎么先用ua.base训练,再用ua.test测试呢?mahout支持这种输入吗?(weka中分类方法实验时,分别加载训练集和测试集的)(3)我看了一些文章,多数文章核心的部分是结合应用特征和属性计算uesr对item的preference,而在你的另一篇博文“Netflix 推荐系统:第二部分”中,提到Netflix不仅仅使用预测评分,而是将热门程度和预测评分进行线性加权f(u, v) = w1*p(v) + w2*r(u, v) + b,然后依据f(u,v)值进行排序。我想知道这个f(u,v)与预测评分有什么本质的区别?是不是博文中的“预测评分”是单纯的依据相似用户或item的信息得出的评分预测,与其他应用相关的属性无关?我个人觉得f(u,v)是一种广义上的评分预测。不好意思,又写了这么多问题。再一次表达我的谢意*_*


回答:

关于你的第一个问题(1)线下计算大概是怎样实现的?其实你自己给的答案是正确的,我这里简单做下补充:这个问题可以说是推荐系统最核心的问题,很多公司对这部分内容一般都只是介绍个大概,细节都秘而不宣,所以这部分所涉及的内容是很多的,无论是计算量,还是技术难度都非常大。一般情况下,一个成熟的推荐系统,都会有两部分组成:离线部分和在线部分。离线部分完成的是相关性的计算,计算结果一般会持久化到 MySQL 或诸如 Redis 的 K-V 数据库中,也可以存储到 HBase 这类分布式存储系统中(据我了解到 facebook 推荐系统的相关性数据就是存储到 HBase 中的)。当然具体的存储方式要视你的数据规模(存储成本)和实际场景(如读写比例、系统结构等)而定。有了相关性数据,在线部分只需要读取用户特征(如历史行为中的商品),然后到相关表找查找匹配相关结果就可以得到初始的推荐结果。另外要告诉你一点,业界各家公司的推荐系统,在线部分大部分是相似的,主要区别和创新主要都集中在离线部分。 

关于你的第二个问题(2)训练集和测试集问题?这主要是一个机器学习中的监督学习过程,这在我上面的回复中有详细的介绍。在 Mahout 中有一个 RecommenderEvaluator 的接口,通过接口中的 evaluate 方法,可以完成对某一个推荐算法的评估,也可以根据这个接口进行自定义的扩展。而在 grouplens 的 100k 的数据中,从 u1.base,u1.test 到 u5.base,u5.test 这 5 组数据集都是从 u.data 中根据 4:1 的比例抽取出来的,其中 .base 是训练集,.test 是测试集。grouplens 的原文介绍是“The data sets u1.base and u1.test through u5.base and u5.test are 80%/20% splits of the u data into training and test data.” 。在训练和测试过程中,第一步:使用 u1.base 进行训练,说具体一点就是基于 u1.base 构建一个 recommender,然后为 u1.base 中的所有 user 产生推荐结果,假设推荐结果集为 u1.result;第二步:比较 u1.result 和 u1.test 中的数据重合度,重合度越高说明算法的准确率越高。如果是直接使用 Mahout 提供的 RecommenderEvaluator,那么仅需要使用一个文件—— u.base,把 u.base 作为 DataModel 的 file,并指定 trainingPercentage 为 0.8,指定 evaluationPercentage 为 1.0 就可以了,Mahout 会自动把 u.base split 成两个文件,train 文件和 test 文件。源码为“splitOneUsersPrefs(trainingPercentage, trainingPrefs, testPrefs, userID, dataModel);”

关于你的第三个问题(3)推荐结果排序和预测评分的关系?在我的博文《Netflix 推荐系统:第二部分》中,f(u, v) 是一个排序分值函数(rank function),而预测分值 p(v) 是函数 f 的一个维度,为什么会这样呢?因为在把推荐结果展现给用户之前,通常需要对推荐结果进行排序,把用户最有可能点击或购买的物品排列在前,计算物品的排序需要综合考虑评分预测值、物品的热门程度、物品的新颖度等等因素,每一个因素可以看成是函数 f(u, v) 的一维。一般而言,会为每个用户都计算一个 f(u, v) 函数,因为一个个性化的推荐系统,排序也要是个性化的,计算的过程是离线完成的,具体你再详细看下博文的原文。

你可能感兴趣的:(Mahout)