【导语】推荐系统,应该是敏捷运营的前提,也是定向广告的前提,互联网运营平台的敏捷化运营,相关的数据挖掘和分析工作,需要这样的云计算平台来支撑,云不应该是虚的。那就做实它。free hit counters

从现有的体系看,基本上都是基于 Hadloop+Mahout+HDFS结构。

P1:

基于云计算的电子商务推荐平台的构建分析


林立宇
2005年硕士毕业于中山大学,现就职于中国电信股份有限公司广东研究院信息应用开发部,主要从事互联网应用、云计算、数据挖掘、知识管理等方面的研究工作。陈云海
中国电信股份有限公司广州研究院信息业务研发室主任,主要研究方向为互联网应用、虚拟化、云计算、自然语言处理、知识管理及应用。


1    引言
随着电子商务的迅猛发展,其信息结构越来越复杂,信息量越来越庞大,用户经常迷失在海量的商品信息中,而商家也无法在海量的用户信息中建立有效的客户关系。电子商务推荐系统能够模拟商店销售人员,根据用户的需求自动推荐商品,帮助商家建立客户关系,并有效聚焦目标客户群。为了更高效地管理海量的商品信息及用户信息,本文提出将电子商务推荐系统构建在云计算基础平台上的解决方案,提高海量数据挖掘和商业智能分析的能力,以较低的成本实现高性能计算,满足中国电信动态扩展的电子商务业务需求。

2    电子商务推荐系统概念及分类
2.1  什么是电子商务推荐系统
在电子商务平台中,电子商务推荐系统具有以下三方面的作用。
(1)将浏览者转变为购买者,帮助用户快速找到需要的商品;
(2)提高交叉销售能力,基于用户已购买的商品,推荐相关商品;
(3)提高用户忠诚度,细分和聚焦目标用户群。
2.2  电子商务推荐系统分类
(1)基于内容过滤的推荐系统。比较商品之间的相似性,推荐与目标用户已选择过的商品相似的商品。
(2)基于协同过滤技术的推荐系统。学习目标用户和历史用户之间购买行为的相似性,从而根据相似历史用户的购买行为生成推荐结果。
(3)基于数据挖掘技术的推荐系统。收集用户大量的各种行为和注册信息,利用关联规则、聚类、分类等数据挖掘技术进行推荐。
(4)混和型推荐系统。综合使用前面各种推荐技术,提高推荐系统的性能和推荐质量。

3   云计算概念及相关技术
3.1  什么是云计算
云计算把计算及存储以服务的形式提供给互联网用户,用户所使用的数据、服务器、应用软件、开发平台等资源都来自互联网上的虚拟化计算中心,该计算中心负责对分布在互联网上的各种资源进行分配、负载的均衡、软件的部署、安全的控制等。云计算方便了用户对计算资源的获取和管理,从而降低成本。
3.2  云计算的特征
(1)以互联网为中心。存储和运算能力分布在网络所连接的各个节点之中,从而弱化终端的计算能力,使互联网的计算架构由“服务器+客户端”向“云服务平台+客户端”演进。
(2)虚拟化。将底层的硬件,包括服务器、存储与网络设备全面虚拟化,建立起一个共享的可以按需分配的基础资源池。
(3)动态扩展。底层的资源可以随需分配和自动增长,而上层的数据及应用可以根据业务型态的不同需求,搭配出各种互相隔离的应用,形成一个服务导向的IT架构。
(4)可运营的业务支撑体系。云计算服务运营平台必须拥有业务支撑体系,包括容量规划、计费、监控、安全、可扩展、可升级等功能。
3.3  云计算开源框架Hadoop
Hadoop是Apache开源组织的一个云计算开源框架,它的上层实现了Google的Map/Reduce算法,使计算任务分布到一个由普通机器组成的超大集群上并发执行。底层的分布式文件系统HDFS具有高容错性和高吞吐量,以较 低的成本将海量文件存储在普通机器集群上。
3.4  分布式数据挖掘中间件库Mahout Mahout是开源的可扩展的分布式数据挖掘中间件库,实现了聚类、分类、协同过滤、进化编程等数据挖掘 算法,能够高效地运行在Hadoop云计算框架上,方便开发人员快捷地创建基于云计算的海量数据挖掘应用,以较低的成本实现高性能、可扩展的电子商务推荐应用。

4  应用云计算技术构建中国电信的电子商务推荐系统
4.1  中国电信发展电子商务推荐应用面临的问题 中国电信电子商务应用主要集中在网上营业厅和号 码百事通业务,电子商务推荐应用的发展面临以下问题。
(1)高性能计算的需求。中国电信的电子商务平台涉及EDC和BSS、MSS、OSS、EDI等业务支撑系统,彼此
独立的系统无法共享计算资源,资源利用率低下;电子商务的商品信息和用户信息是海量级的,且分布存储在彼此 独立的系统中,需要构建高性能的分布式数据挖掘台。
(2)可伸缩性的需求。推荐系统的数据分析任务具有 阶段性和突发性,在特定的时间窗口下需要大量的计算资源,要求可以按需分配资源;电子商务的应用场景非常复 杂,要求推荐系统根据业务型态的不同需求,搭配出不同 的推荐模型。
(3)混合型推荐的需求。由于中国电信的商品资源还 没有获得足够多的用户评价,存在数据稀疏和冷开始的问 题,因此不能够采用单纯的协同过滤技术,需要结合内容
T 过滤技术;推荐模型还需要对用户位置、访问日志和账单等业务信息进行数据挖掘,提高推荐质量。
(4)复杂数据结构的分析需求。随着用户数和商品的 快速增长网上营业厅和号码百事通业务等电子商务应用的数据结构越来越复杂,产品更新变化快,产品之间的直接关联度也比较低,需要围绕用户信息构建动态扩展的推荐模型,并利用动态扩展的云计算平台进行海量数据挖掘。
4.2  基于云计算的电子商务推荐平台的应用意义 针对中国电信发展电子商务推荐应用面临的问题, 本文提出利用Mahout和Hadoop等云计算技术构建中国电信的电子务推荐系统的解决方案,对于中国电信发展电子商务业务具有以下重大的应用意义。
(1)提升电子商务的交易量。针对不同的电子商务应用场景,能够搭配出相应的推荐模型,并且根据不同用户的需求,高效精确地推荐商品,提升电子商务的交易量,促进转型业务的发展。
(2)提升各类电子商务产品的交叉销售能力。各种相关的业务系统通过Hadoop基础平台共享计算和存储资源,并且利用Mahout中间件对来自于不同业务系统的各类产品和用户信息进行数据分析,进行交叉推荐或套餐定制,提升交叉销售能力,在产品销售上促进业务融合。
(3)用户社群发现。利用Mahout的聚类算法分析用户的交易行为,形成有相似兴趣和需求的用户社群,进行细分营销,推荐用户社群共同关注的商品。
(4)提升用户忠诚度。分析潜在流失的用户,根据关联规则挖掘其潜在的兴趣点,进行推荐,提升用户的忠诚度。
(5)用户价值发现。分析用户在电子商务社交网络中的位置对其价值的影响,从而有效挖掘出VIP用户,进行重点推荐。
4.3  基于云计算的电子商务推荐平台的运营体系架构基于云计算的中国电信电子商务推荐平台的运营体系架构(如图1)包括分布式文件系统层、分布式计算层、数据分析中间件层和业务应用层,其中分布式文件系统层和分布式计算层是利用Hadoop构建的,而数据分析中间件层是根据业务应用在Mahout的基础上定制,并且以服务方式供用户访问。平台的每一层都有相应的云计算管理模块,包括数据安全、资源监控、资源动态调度、资源动态部署、资源规划和虚拟化等功能,保证每一层都具有高可靠性和可伸缩性。电子商务平台的相关业务系统可以直接在此平台上搭建,也可以集成到此平台上共享计算和存储资源,构建所需的推荐模型。在数据集成方面,可以利用数据分析中间件层导入业务系统的源数据进行分析,也可以把业务系统的数据直接存储到分布式文件系统层进行管理和访问。

(1)分布式文件系统层
本文提出利用Hadoop HDFS实现高可靠的分布式数据文件存储功能,将海量数据分布存储在多台计算机集群上,把文件进行分块存储,为实现容错自动进行分块复制。
HDFS由一个管理节点(Namenode)和多个数据节点(Datanode)组成。管理节点是中心服务器,负责管理文件系统的名字空间以及客户端对文件的访问,比如打开、关闭、重命名文件或目录,同时它还决定了数据块和数据节点的映射关系,即文件系统的元数据。集群中每一个节点配置一个数据节点,负责管理本节点上的数据存储,并处理客户端的读写请求,进行数据块的创建、删除和复制。从内部看,一个文件被分成一个或多个数据块,存储在一组数据节点上。HDFS为上层的分布式计算层提供输入数据、中间结果以及输出数据的载体,发挥MapReduce可伸缩性的优势;也可以把业务系统的数据直接存储到分布式文件系统层进行管理和访问。
(2)分布式计算层
本方案采用MapReduce作为分布式并行计算模型,将大型任务分成很多细粒度的子任务,这些子任务分布式且并行地在多个计算节点上进行调度和计算,从而在云平台上获得对海量数据的处理能力。在Hadoop MapReduce 中,Map 操作和Reduce 操作的执行被包裹为任务(task),而任务又以Map-Reduce 对的形式被包裹为作业(job)。负责在Hadoop集群节点上安排任务执行的软件被称作TaskTracker,每个计算节点上部署一个。负责在集群范围内调度作业和任务执行的软件被称作JobTracker,在Hadoop 集群内挑选独立的机器来部署。
(3)数据分析中间件层
Mahout已经实现了聚类、分类、协同过滤、进化编程等数据挖掘算法,并且允许扩展,根据推荐应用层的业务需求定制中国电信的Mahout算法库,并且以服务方式供推荐应用层调用。Taste是Mahout 提供的一个协同过滤算法的高效实现,它是一个基于 Java 实现的可扩展的,高效的推荐引擎中间件。Taste 既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法。同时,Taste 不仅仅只适用于 Java 应用程序,它可以作为内部服务器的一个组件以HTTP和Web服务的形式向外界提供推荐的逻辑。Taste的设计使它能满足企业对推荐引擎在性能、灵活性和可扩展性等方面的要求。除了Taste推荐模型,还可以进一步定制、扩展和组合Mahout的聚类、关联规则、进化编程等数据挖掘算法,为推荐应用层生成更多的推荐模型。典型的电子商务推荐内容的生成流程包括数据建模、数据导入、数据预处理、推荐模型处理、数据输出等过程。数据分析中间件层依托下层的分布式计算层和分布式文件系统层,可以处理海量数据集和快速增长的数据集,比如每日更新的用户访问日志。由于Mahout是依附于最通用的云计算平台Hadoop上,可有效地与其它云计算中间件进行协调整合。
(4)推荐应用层
实现内容过滤推荐、协同过滤推荐、混合推荐、用户群发现、用户价值分析、用户流失分析等电子商务推荐应用,满足中国电信电子商务的业务需求。
4.4  基于云计算的电子商务推荐平台的发展重点
(1)资源整合
以现有的电子商务推荐系统为基础,进行资源整合,实现物理资源的虚拟化,通过虚拟化技术实现资源池化和资源动态扩展等功能,利用分布式文件系统动态存储各个电子商务系统的数据,实现基础平台与应用平台的扩展。
(2)依托号百平台推出亮点应用
目前中国电信最主要的电子商务系统是号码百事通平台,基于云计算的电子商务推荐平台可以依托号百平台推出亮点应用,以亮点应用带动基础平台的发展。
(3)应用扩展
在整合的基础上扩展平台,开发和部署更多的推荐模型提供给推荐业务,并且将开发接口和运行时接口标准化,提供较为完善的开发套件,鼓励和吸引合作伙伴共同丰富平台和应用的功能,与其它电子商务服务提供商合作共赢。

5    难点和风险
(1) 数据稀疏性问题和冷开始问题
在推荐系统建立初期,由于系统资源还没有获得足够多的评价,系统很难利用这些评价来发现相似的用户,这就是数据稀疏性问题;而如果一个新项目没有人去评价它,那么它便得不到推荐,推荐系统就失去了作用,也就是冷开始问题。因此推荐系统建立初期,不能够采用单纯的协同过滤
技术,需要结合内容过滤技术定制混合型推荐模型。
(2)实时性与推荐质量之间的平衡
推荐系统的推荐精度和实时性是一对矛盾。大部分推荐技术在保证实时性要求的同时,是以牺牲推荐系统的推荐质量为前提的。在保证推荐质量的基础上,为了提高实时性可以预先对用户行为信息进行聚类,定制混合型推荐模型。
(3)用户隐私保护研究
由于推荐系统需要分析用户的购买习惯和兴趣爱好,涉及到用户隐私问题,必须提出一个有效的保护用户隐私的机制,才能顺利实现个性化推荐服务。

6    总结
应用Hadoop和Mahout等云计算技术构建中国电信的电子商务推荐系统,能够以较低的成本实现高性能、动态扩展的电子商务推荐基础平台,提升百事购、网上商城等电子商务业务的交易量,提升各类电子商务产品的交叉销售能力,提升用户忠诚度和用户价值。由于Mahout是依附于最通用的云计算平台Hadoop上,可以通过整合其它
云计算中间件,扩展平台的功能,促进中国电信云计算基础架构的发展,并且进一步地应用到物联网中,为三网融合下的电子商务提供高性能、动态扩展的推荐基础平台。

参考文献
1      张敏 陈云海 林立宇 电信运营商云计算数据中心的构建分析. 电信技术,  2009, (6):100-104
2      赵晨婷, 马春娥. 基于 Apache Mahout 构建社会化推荐引擎.http://www.ibm.com/developerworks/cn/java/j-lo-mahout/
3      邓秀勤, 姜莲花. 电子商务推荐系统研究. 辽东学院学报, 2005, (7): 43-38
4      多雪松, 张晶, 高强. 基于Hadoop 的海量数据管理系统. 微计算机信息,  2010, (26):1-5

P2:

[推荐系统]Collaborative filtering 学习总结

Collaborative filtering, 即协同过滤,是一种新颖的技术。最早于1989年就提出来了,直到21世纪才得到产业性的应用。应用上的代表在国外有Amazon.com,Last.fm,Digg等等。

最近由于毕业论文的原因,开始研究这个题目,看了一个多星期的论文与相关资料之后,决定写篇总结来总结一下最近这段时间资料收集的成果。

在微软1998年的那篇关于协同过滤的论文[1]中,将协同过滤分成了两个流派,一个是Memory-Based,一个是Model-Based。关于Memory-Based的算法,就是利用用户在系统中的操作记录来生成相关的推荐结果的一种方法,主要也分成两种方法,一种是User-Based,即是利用用户与用户之间的相似性,生成最近的邻居,当需要推荐的时候,从最近的邻居中得到推荐得分最高的几篇文章,用作推荐;另外一种是Item-Based,即是基于item之间的关系,针对item来作推荐,Amazon.com即是使用这种方法,使用一种基本的方法来得到不俗的效果。而实验结果也表明,Item-Based的做法比User-Based更有效[2]。而对于Model-Based的算法,即是使用机器学习中的一些建模算法,在线下对于模型进行预计算,在线上能够快速得出结果。主要使用的算法有 Bayesian belief nets , clustering , latent semantic , 最近几年又出现了使用SVM 等的CF算法。最近几年又提出一种新的分类,content-based,即是对于item的内容进行分析,从而进行推荐。而现阶段,比较优秀的一些应用算法,则是将以上几种方法,混合使用。比较说Google News[3],在它的系统中,使用了一种将Memory-Based与Model-Based两种方法混合的算法来处理。在Google的那篇论文里面,它提到了如何构建一个大型的推荐系统,其中Google的一些高效的基础架构如:BigTable,MapReduce等得到很好的应用。

在这篇总结中,主要论及最基本的Memory-Based算法。对于Memory-Based算法,主要有两个步骤,第一个是计算相似性,另外一个是进行推荐。

对于第一步,主要是于线下计算item-item或者user-user之间的相似性,主要使用的算法有Correlation-Based,如Pearson correlation [4], Jaccard coefficient[5]等,与Vector Cosine-Based Similarity , 和在实验中被验证具有最好效果的Regression 。 第二步,则是生成相关的推荐项目的过程。主要是根据上一步得出的最近邻,从其中得出最相关的Top-N个推荐的项目作为结果。这种方法被沿用多年,大多数的推荐系统都是使用这种方法构建的。

而对于大多数的项目而言,推荐系统都不可避免地面临以下几个问题[6]:

1.数据过度松散,当应用变得庞大,数据集开始增大的时候,就会出现这个问题了。可能大量的用户只是评价了一小部分的项目,而大多数的项目是没有进行评分的。 这个时候就会出现数据过度松散的问题。

2.同义项目问题,对于同义的项目,在系统中可能具有不同的标识符,对于这些项目之间的相关性就会被忽略。

3.垃圾攻击,对于一些利用系统进行恶意传播的用户,可能会制造一些虚假的评价,造成系统推荐的不正确行为。

4.冷启动问题,对于新使用系统的用户,系统中并没有相关的操作记录,没法生成相关的推荐。

总体而言,现在的推荐系统还是面临不少的问题。而在产业界的成功也会促使这项技术会继续发展。

我的下一步计划是实现一个小型的推荐系统,然后再继续阅读相关文献,逐步提升。

收集到一些相关资料:

书籍:

[1]《Programming Collaborative Intelligence》,中文译名为《集体智慧编程》。是一本理论与实践的好书,手把手教你如何写一个推荐系统,不过其中的算法比较简单,但是对于入门是一本好书。

[2]《AlgorithmsIntelligentWeb》,也是非常浅显,重于实践的书,其中第二单,讲解了一个简单的推荐系统的搭建,并提供了源码,供学习。

组织:

[1]Resys Group,国内一个关于推荐引擎的小组,其中不乏牛人,定期也会举办活动。

[2]GroupLens,老字号的推荐引擎研究小组,它们的主页上有很多的资讯,推荐。

博客:

[1]Beyond.Search, Resys Group的创始人之一,里面有不少不错的博文,可以获得大量关于推荐系统发展的资讯。

[2]Daniel Lemire’s blog ,一个研究人员的博客,推荐。

开源软件库:

[1] Taste ,已经整合到Apache里的Mahout里面了,一个非常经典的推荐系统库。

参考文献:

【1】John S. Breese ,David Heckerman , Carl Kadie.Empirical Analysis of Predictive Algorithms for Collabrative Filtering

【2】 Badrul Sarwar , George Karypis , Joseph Konstan , John Riedi.Item-Based Collaborative Filtering Recommendation Algorithm

【3】Abhinandan Das , Mayur Datar , Ashutosh Garg.Google News Personalization : Scalable Online Collaborative Filtering ,

【4】Paul Resnick , Neophytos lacovou , Mitesh Suchak , Peter Bergstrom , John Riedl .GroupLens: An Open Architecture For Collaborative Filtering of Netnews

【5】A.Broder..On the resemblance and containment of documents

【6】XiaoYuan Su , Taghi M.Khoshgoftaar.A Survey of Collaborative Filtering Techiniques ,

基于 Apache Mahout 构建社会化推荐引擎

简介: Web 2.0 的一个核心思想就是“群体智慧”,即基于大众行为,为每个用户提供个性化的推荐。这使得如何让用户能更快速更准确的获得所需要的信息,成为了 Web 应用成败的关键。Apache Mahout 是 ASF(Apache Software Foundation)的一个较新的开源项目,提供机器学习领域的一些经典算法的高效实现。本文主要讲述如何基于 Apache Mahout 来构建社会化推荐引擎,帮助 Web 应用开发者更高效的实现个性化推荐功能,从而提高最终用户满意度。

本文的标签: apache, java_技术, mahout, web_2.0, 基于, 应用开发, 开放源码, 推荐, 推荐引擎, 构建社会化推荐引擎… 更多标签

推荐引擎简介

推荐引擎利用特殊的信息过滤(IF,Information Filtering)技术,将不同的内容(例如电影、音乐、书籍、新闻、图片、网页等)推荐给可能感兴趣的用户。通常情况下,推荐引擎的实现是通过将用户的个人喜好与特定的参考特征进行比较,并试图预测用户对一些未评分项目的喜好程度。参考特征的选取可能是从项目本身的信息中提取的,或是基于用户所在的社会或社团环境。

根据如何抽取参考特征,我们可以将推荐引擎分为以下四大类:

  • 基于内容的推荐引擎:它将计算得到并推荐给用户一些与该用户已选择过的项目相似的内容。例如,当你在网上购书时,你总是购买与历史相关的书籍,那么基于内容的推荐引擎就会给你推荐一些热门的历史方面的书籍。
  • 基于协同过滤的推荐引擎:它将推荐给用户一些与该用户品味相似的其他用户喜欢的内容。例如,当你在网上买衣服时,基于协同过滤的推荐引擎会根据你的历史购买记录或是浏览记录,分析出你的穿衣品位,并找到与你品味相似的一些用户,将他们浏览和购买的衣服推荐给你。
  • 基于关联规则的推荐引擎:它将推荐给用户一些采用关联规则发现算法计算出的内容。关联规则的发现算法有很多,如 Apriori、AprioriTid、DHP、FP-tree 等。
  • 混合推荐引擎:结合以上各种,得到一个更加全面的推荐效果。

随着互联网上数据和内容的不断增长,人们越来越重视推荐引擎在互联网应用中的作用。可想而知,由于互联网上的数据过多,用户很难找到自己想要的信息,通过提供搜索功能来解决这个问题是远远不够的。推荐引擎可以通过分析用户的行为来预测用户的喜好,使用户能更容易找到他们潜在需要的信息。这里以电子商务应用中的推荐引擎为例来说明推荐引擎在互联网应用中的重要性。

电子商务推荐系统 (E-Commence Recommendation System) 向客户提供商品信息和购买建议,模拟销售人员帮助客户完成购买过程。智能推荐系统的作用可以概括为:将电子商务网站的浏览者转变为购买者 ,提高电子商务网站的交叉销售能力,提高客户对电子商务网站的忠诚度。

电子商务推荐系统的界面表现形式有以下几种:

  • 浏览:客户提出对特定商品的查询要求,推荐引擎根据查询要求返回高质量的推荐;
  • 相似商品:推荐引擎根据客户购物篮中的商品和客户可能感兴趣的商品推荐与它们类似的商品;
  • Email:推荐系统通过电子邮件的方式通知客户可能感兴趣的商品信息;
  • 评论:推荐系统向客户提供其他客户对相应产品的评论信息。

Apache Mahout 简介

Apache Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。经典算法包括聚类、分类、协同过滤、进化编程等等,并且,在 Mahout 的最近版本中还加入了对 Apache Hadoop 的支持,使这些算法可以更高效的运行在云计算环境中。

Taste 简介

Taste 是 Apache Mahout 提供的一个协同过滤算法的高效实现,它是一个基于 Java 实现的可扩展的,高效的推荐引擎。Taste 既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法。同时,Taste 不仅仅只适用于 Java 应用程序,它可以作为内部服务器的一个组件以 HTTP 和 Web Service 的形式向外界提供推荐的逻辑。Taste 的设计使它能满足企业对推荐引擎在性能、灵活性和可扩展性等方面的要求。

Taste 工作原理
图 1. Taste 的主要组件图
图 1. Taste 的主要组件图
Taste 由以下五个主要的组件组成:

  • DataModel:DataModel 是用户喜好信息的抽象接口,它的具体实现支持从任意类型的数据源抽取用户喜好信息。Taste 默认提供 JDBCDataModel 和 FileDataModel,分别支持从数据库和文件中读取用户的喜好信息。
  • UserSimilarity 和 ItemSimilarity:UserSimilarity 用于定义两个用户间的相似度,它是基于协同过滤的推荐引擎的核心部分,可以用来计算用户的“邻居”,这里我们将与当前用户口味相似的用户称为他的邻居。ItemSimilarity 类似的,计算内容之间的相似度。
  • UserNeighborhood:用于基于用户相似度的推荐方法中,推荐的内容是基于找到与当前用户喜好相似的“邻居用户”的方式产生的。UserNeighborhood 定义了确定邻居用户的方法,具体实现一般是基于 UserSimilarity 计算得到的。
  • Recommender:Recommender 是推荐引擎的抽象接口,Taste 中的核心组件。程序中,为它提供一个 DataModel,它可以计算出对不同用户的推荐内容。实际应用中,主要使用它的实现类 GenericUserBasedRecommender 或者 GenericItemBasedRecommender,分别实现基于用户相似度的推荐引擎或者基于内容的推荐引擎。

Taste 的安装与简单的 Demo 实现

安装 Taste 的软件需求:

  • 如果需要 build 源代码或者例子,需要 Apache Ant 1.5+ 或 Apache Maven 2.0.10+。
  • Taste 应用程序需要 Servlet 2.3+容器,例如 Jakarta Tomcat
  • Taste 中的 MySQLJDBCDataModel 实现需要 MySQL 4.x+数据库。

安装 Taste 并运行 Demo:

  1. 从 SVN 或是下载压缩包得到 Apache Mahout 的发布版本:
  2. 从 Grouplens 下载数据源:“1 Million MovieLens Dataset”
  3. 解压数据源压缩包,将 movie.dat 和 ratings.dat 拷贝到 Mahout 安装目录下的 taste-web/src/ main/resources/org/apache/mahout/cf/taste/example/grouplens 目录下。
  4. 回到在 core 目录下,运行”mvn install”,将 Mahout core 安装在本地库中。
  5. 进入 taste-web, 拷贝 ../examples/target/grouplens.jar 到 taste-web/lib 目录
  6. 编辑 taste-web/recommender.properties,将 recommender.class 设置为 org.apache.mahout. cf.taste.example.grouplens.GroupLensRecommender。
  7. 在 Mahout 的安装目录下,运行”mvn package”。
  8. 运行“mvn jetty:run-war”。这里需要将 Maven 的最大内存设置为 1024M,MAVEN_OPTS=-Xmx1024M。如果需要在 Tomcat 下运行,可以在执行”mvn package”后,将 taste-web/target 目录下生成的 war 包拷贝到 Tomcat 的 webapp 下,同时也需要将 Java 的最大内存设置为 1024M,JAVA_OPTS=-Xmx1024M,然后启动 Tomcat。
  9. 访问“http://localhost:8080/[your_app]/RecommenderServlet?userID=1”,得到系统为编号为 1 的用户的推荐内容。参看图 2,Taste demo 运行结果界面,每一行第一项是推荐引擎预测的评分,第二项是电影的编号。
  10. 同时,Taste 还提供 Web 服务访问接口,通过以下 URL 访问:http://localhost:8080/[your_app]/RecommenderService.jws

    WSDL 文件:http://localhost:8080/[your_app]/RecommenderService.jws?wsdl

    也可以通过简单的 HTTP 请求调用这个 Web 服务:

    http://localhost:8080/[your_app]/RecommenderService.jws?
    method=recommend&userID=1&howMany=10

图 2. Taste Demo 运行结果界面
图 2. Taste Demo 运行结果界面
使用 Taste 构建推荐引擎实例 – 电影推荐引擎

根据上面的步骤,我们可以得到一个简单的推荐引擎 demo 环境,下面介绍如何使用 Taste 方便地构建自定义的推荐引擎。

抽取 Taste 工具包

直接使用 Mahout 的项目环境进行编码,需要使用 Ant 或者 Maven 进行编译,整个过程比较复杂,这里我们将构建推荐引擎所需要的工具包从 Mahout 工程中抽取出来,从而方便的构建自定义的推荐引擎。

在 Eclipse 中创建 Web 应用的工程 MovieSite,将 demo 时生成的推荐引擎 Web 应用的 war 包解压缩,将 lib 下的 jar 文件拷贝到 MovieSite 的 lib 目录下。这样我们就可以方便的编写自己的推荐引擎。
图 3. MovieSite 工程中引用的 jar 文件
图 3. MovieSite 工程中引用的 jar 文件
数据建模

这里我们想要编写一个电影推荐引擎,第一步需要对数据进行建模,分析应用中涉及的主要实体以及实体间的关系,从而设计数据库存储,程序中的类,以及推荐引擎的 DataModel。
图 4 电影和用户信息数据模型
图 4 电影和用户信息数据模型
数据模型中存在以下实体:

  • Movie:表示电影,包含电影的基本信息:编号、名称、发布时间、类型等等。
  • User:表示用户,包含用户的基本信息:编号、姓名、邮件等等。
  • Movie Reference:表示某个用户对某个电影的喜好程度,包含用户编号、电影编号、用户的评分以及评分的时间。
  • Movie Similarity:表示两个电影的相似度(这里的相似度是双向的),包括两个电影编号、电影的相似度。两个电影的相似度可以通过电影的基本信息计算得到。

下面我们就基于这个数据模型设计数据库的存储以及推荐引擎的 DataModel。

  1. 1 .创建 MySQL 数据库存储电影和用户的信息,用户的喜好信息以及电影的相似度。

    清单 1. 创建数据库 SQL

    						
     CREATE DATABASE movie; 
     USE movie; 
     CREATE TABLE movies (  // 保存电影相关的信息。
        id INTEGER NOT NULL AUTO_INCREMENT, 
        name varchar(100) NOT NULL, 
        published_year varchar(4) default NULL, 
        type varchar(100) default NULL, 
     --    ...more movie information... 
        PRIMARY KEY (id) 
     ); 
    
     CREATE TABLE users (  // 保存用户信息
        id INTEGER NOT NULL AUTO_INCREMENT, 
        name varchar(50) NOT NULL, 
        email varchar(100) default NULL, 
     --    ...more user information... 
        PRIMARY KEY (id) 
     ); 
    
     CREATE TABLE movie_preferences (  // 保存用户对电影的评分,即喜好程度
        userID INTEGER NOT NULL, 
        movieID INTEGER NOT NULL, 
        preference INTEGER NOT NULL DEFAULT 0, 
        timestamp INTEGER not null default 0, 
        FOREIGN KEY (userID) REFERENCES users(id) ON DELETE CASCADE, 
        FOREIGN KEY (movieID) REFERENCES movies(id) ON DELETE CASCADE 
     ); 
    
     CREATE TABLE movie_similarity (   // 保存电影和电影的相似程度
        movieID1 INTEGER NOT NULL, 
        movieID2 INTEGER NOT NULL, 
        similarity DOUBLE NOT NULL DEFAULT 0, 
        FOREIGN KEY (movieID1) REFERENCES movies(id) ON DELETE CASCADE, 
        FOREIGN KEY (movieID2) REFERENCES movies(id) ON DELETE CASCADE 
     ); 
    
     CREATE INDEX movie_preferences_index1 ON movie_preferences ( userID , movieID ); 
     CREATE INDEX movie_preferences_index2 ON movie_preferences ( userID ); 
     CREATE INDEX movie_preferences_index3 ON movie_preferences ( movieID );

    在实际应用中,我们需要将应用中的实例数据写入到数据库中。作为例子,这里将从 GroupLen 下载的数据源写入数据库。

  2. 设计实现推荐引擎的 DataModel。由于上面采用数据库存储用户的喜好信息,这里需要基于数据库的推荐引擎实现。这里扩展 MySQLJDBCDataModel 实现电影推荐引擎的 DataModel 实例。

    清单 2. Taste DataModel 的实现

    						
     public class MovieDataModel extends MySQLJDBCDataModel { 
    
        // 保存用户对电影的评分的数据库表名
        public final static String PERFERENCETABLE = "movie_preferences";  
        public final static String USERID_COLUMN = "userID";   // 表中用户标识的列名
        public final static String ITEMID_COLUMN = "movieID";  // 表中电影标识的列名
        public final static String PERFERENCE_COLUMN = "preference";  // 表中评分的列名
    
        public MovieDataModel(String dataSourceName) throws TasteException { 		
            super(lookupDataSource(dataSourceName), PERFERENCETABLE, USERID_COLUMN, 
                ITEMID_COLUMN, PERFERENCE_COLUMN); 
        } 
    
        public MovieDataModel() { 
            //DBUtil.getDataSource() 将返回应用的数据源
            // 此应用是 J2EE 应用,所以这里会采用 JDNI 的方式创建数据库链接。
            super(DBUtil.getDataSource(), PERFERENCETABLE, USERID_COLUMN, 
                ITEMID_COLUMN, PERFERENCE_COLUMN); 
        } 
     }

推荐引擎实现

前面介绍了数据建模和 DataModel 的实现,下面来详细介绍推荐引擎的实现。如前面介绍的,Taste 既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法。下面详细介绍如何扩展 Taste 的推荐引擎接口,实现基于用户相似度的推荐引擎,基于内容相似度的推荐引擎,以及 Slope One 的推荐引擎。Slope One 是一种非常快速简单的基于项目的推荐方法,需要使用用户的评分信息。
清单 3. 基于用户相似度的推荐实现

				
 public class UserBasedRecommender implements Recommender { 

    private final Recommender recommender; 

    public UserBasedRecommender() throws IOException, TasteException { 
        this(new MovieDataModel()); 
    } 

    public UserBasedRecommender(DataModel model) throws TasteException { 

        UserSimilarity userSimilarity = new PearsonCorrelationSimilarity(model);  
        userSimilarity.setPreferenceInferrer(new AveragingPreferenceInferrer(model)); 

        UserNeighborhood neighborhood = 
            new NearestNUserNeighborhood(3, userSimilarity, model); 
        recommender = new CachingRecommender( 
            new GenericUserBasedRecommender(model, neighborhood, userSimilarity)); 
    } 

    // 对外提供的推荐的接口,参数为用户标识和推荐项的个数
    public List<RecommendedItem> recommend(long userID, int howMany) 
        throws TasteException { 
        return recommender.recommend(userID, howMany); 
    } 

    public List<RecommendedItem> recommend(long userID, int howMany, 
        Rescorer<Long> rescorer) throws TasteException { 
        return recommender.recommend(userID, howMany, rescorer); 
    } 

    // 以下方法都是实现 Recommender 的接口
    public float estimatePreference(long userID, long itemID) throws TasteException { 
        return recommender.estimatePreference(userID, itemID); 
    } 

    public void setPreference(long userID, long itemID, float value) 
        throws TasteException { 
        recommender.setPreference(userID, itemID, value); 
    } 

    public void removePreference(long userID, long itemID) throws TasteException { 
        recommender.removePreference(userID, itemID); 
    } 

    public DataModel getDataModel() { 
        return recommender.getDataModel(); 
    } 

    public void refresh(Collection<Refreshable> alreadyRefreshed) { 
        recommender.refresh(alreadyRefreshed); 
    } 

    public String toString() { 
        return "UserBasedRecommender[recommender:" + recommender + ']'; 
    } 
 }

从上面的代码示例清单 3 可以看出,实现一个推荐引擎需要实现 Recommender 接口,它一般是对于某种 Taste 提供的推荐引擎的扩展,这是对 GenericUserBasedRecommender 进行的扩展,其中最重要的方法就是实例化推荐引擎的构造方法,一般其中涉及以下步骤:

  • 基于 DataModel,计算用户的相似度,这里采用 PearsonCorrelation 算法。
  • 为用户相似度设置相似度推理方法,这里采用了 AveragingPreferenceInferrer。
  • 基于用户相似度计算用户的“邻居”,这里将与该用户最近距离为 3 的用户设置为该用户的“邻居”。
  • 使用以上得到的用户相似度对象和邻居用户的计算方法对象创建一个 GenericUserBasedRecommender 的实例。一般情况下,这时都采用 CachingRecommender 为 RecommendationItem 进行缓存,从而提高访问速度。

清单 4. 基于内容相似度的推荐实现

				
 public class ItemBasedRecommender implements Recommender { 

    private final Recommender recommender; 

    public ItemBasedRecommender() throws IOException, TasteException { 
        this(new MovieDataModel()); 
    } 

    public ItemBasedRecommender(DataModel dataModel) throws TasteException { 

        Collection<GenericItemSimilarity.ItemItemSimilarity> correlations = 
            MovieSimilarityTable.getAllMovieSimilarities(); 
        ItemSimilarity itemSimilarity = new GenericItemSimilarity(correlations); 
        recommender = new CachingRecommender(new EmbededItemBasedRecommender( 
            new GenericItemBasedRecommender(dataModel, itemSimilarity))); 
    } 

    public List<RecommendedItem> recommend(long userID, int howMany) 
        throws TasteException { 
        return recommender.recommend(userID, howMany); 
    } 

	 ......... 

    //EmbededItemBasedRecommender 类的定义		  
    private static final class EmbededItemBasedRecommender implements Recommender { 

        // 包含一个 GenericItemBasedRecommender 实例;
        private final GenericItemBasedRecommender recommender; 

        private EmbededItemBasedRecommender(GenericItemBasedRecommender recommender) { 
            this.recommender = recommender; 
        } 

        public List<RecommendedItem> recommend(long userID,  int howMany, 
            Rescorer<Long> rescorer) 
            throws TasteException { 
            FastIDSet itemIDs = recommender.getDataModel().getItemIDsFromUser(userID); 
            return recommender.mostSimilarItems(itemIDs.toArray(), howMany, null); 
        } 

    ........ 

 }

从上面的代码示例清单 4 可以看出,与上一个实现类似它是对 GenericItemBasedRecommender 的扩展,它的构造方法涉及以下步骤:

  1. 为了提高推荐引擎的实时响应速度,这里需要对电影信息的预处理,将电影的相似度提前计算好存储在数据库中的 movie_similarity 表中,然后从数据库中读取所有的电影的相似度,用于创建 ItemItemSimilarity 的集合。
  2. 基于 ItemItemSimilarity 的集合生成一个内容相似度 ItemSimilarity。
  3. 创建一个 EmbededItemBasedRecommender 实例,它是一个内部类,包含一个 GenericItemBasedRecommender 实例,它的 recommend 方法中,先从 DataModel 中得到该用户评分的电影列表,然后调用 GenericItemBasedRecommender 中的 mostSimilarItems 方法计算出最相似的电影推荐给用户。

清单 5. SlopeOne Recommeder 的实现

				
 public final class MovieRecommender implements Recommender { 

    private final Recommender recommender; 

    public MovieRecommender() throws IOException, TasteException { 
        this(new MovieDataModel()); 
    } 

    public MovieRecommender(DataModel dataModel) throws TasteException { 
        // 创建一个 SlopeOneRecommender 的实例
        recommender = new CachingRecommender(new SlopeOneRecommender(dataModel)); 
    } 

    // 对外提供的推荐的接口,参数为用户标识和推荐项的个数
    public List<RecommendedItem> recommend(long userID, int howMany) 
        throws TasteException { 
        return recommender.recommend(userID, howMany); 
    } 

	 ........ 

 }

Slope One 是一种非常快速简单的基于项目的推荐方法,它只需要使用用户的评分信息。具体的实现,只需要在我们的推荐引擎中包含一个 SlopeOneRecommender 的实例。

推荐引擎 API 设计与实现

完成了推荐引擎的设计与实现,下面我们需要设计一些 REST API,向外暴露推荐功能。为了提高推荐引擎的处理效率,这里采用 Singleton 模式实现一个推荐引擎的单例 MovieRecommenderSingleton。在 Servlet 启动的时候初始化推荐引擎的单例,以后每次调用推荐方法。
清单 6. Servlet 的实现

				
public class MovieRecommenderServlet extends HttpServlet { 
private static final int NUM_TOP_PREFERENCES = 20; 
private static final int DEFAULT_HOW_MANY = 20; 
private Recommender recommender; 
@Override 
public void init(ServletConfig config) throws ServletException { 
super.init(config); 
// 从 web.xml 中读取需要创建的推荐引擎类名
/* 
* <servlet> 
* 	 <servlet-name>movie-recommender</servlet-name> 
* 	 <display-name>Movie Recommender</display-name> 
* 	 <description>Movie recommender servlet</description> 
* 	 <servlet-class> 
*      com.ibm.taste.example.movie.servlet.MovieRecommenderServlet 
*  </servlet-class> 
* 	 <init-param> 
* 		 <param-name>recommender-class</param-name> 
* 		 <param-value> 
*          com.ibm.taste.example.movie.recommender.UserBasedRecommender 
*      </param-value> 
* 	 </init-param> 
* 	 <load-on-startup>1</load-on-startup> 
* </servlet> 
*/ 
String recommenderClassName = config.getInitParameter("recommender-class"); 
if (recommenderClassName == null) { 
throw new ServletException( 
"Servlet init-param \"recommender-class\" is not defined"); 
} 
try { 
MovieRecommenderSingleton.initializeIfNeeded(recommenderClassName); 
} catch (TasteException te) { 
throw new ServletException(te); 
} 
recommender = MovieRecommenderSingleton.getInstance().getRecommender(); 
} 
@Override 
public void doGet(HttpServletRequest request, 
HttpServletResponse response) throws ServletException { 
//Parameters.USER_ID = "userID"
String userIDString = request.getParameter(Parameters.USER_ID);  
if (userIDString == null) { 
throw new ServletException("userID was not specified"); 
} 
long userID = Long.parseLong(userIDString); 
String howManyString = request.getParameter(Parameters.COUNT);  	
//Parameters.COUNT = "count"
int howMany = howManyString == null ? DEFAULT_HOW_MANY : 
Integer.parseInt(howManyString); 
String format = request.getParameter(Parameters.FORMAT);  	
//Parameters.FORMAT = "format"
if (format == null) { 
format = "json"; 
} 
try { 
// 为指定用户计算推荐的电影
List<RecommendedItem> items = recommender.recommend(userID, howMany); 
// 加载电影的相关信息,RecommendMovieList 是保存了一组推荐电影的相关信息和
// 引擎计算得到的他们的 ranking 
RecommendMovieList movieList = new RecommendMovieList(items); 
if ("text".equals(format)) { 
writePlainText(response, movieList); 
} else if ("json".equals(format)) { 
writeJSON(response, movieList); 
} else { 
throw new ServletException("Bad format parameter: " + format); 
} 
} catch (TasteException te) { 
throw new ServletException(te); 
} catch (IOException ioe) { 
throw new ServletException(ioe); 
} 
} 
//details please refer to the src code 
}

以上完成了电影推荐引擎服务器端的编程,下面我们使用 FireFox 的插件 Poster 测试一下 HTTP 请求,查看推荐引擎的返回结果。对任意一个用户,推荐引擎应该基于一定的规则计算得到一组电影以及预计的评分,为了有更好的用户体验,引擎在拿到推荐电影序号的列表后,从电影信息数据库中查询得到电影的相关信息,包括电影的名称,发表时间以及类型等信息。这里我们采用 JSON 作为推荐引擎的响应格式。
图 4. 用 Poster 测试 Servlet 的结果(查看大图
图 4. 用 Poster 测试 Servlet 的结果
用户界面展示

实现一个推荐引擎的最后一步就是编写客户端代码,为电影推荐引擎提供一个友好的用户界面。下面展示一下我们为电影推荐引擎写的一个简单的用户界面:右边红色框中的是该用户已经打分的电影列表,左边蓝色框中是推荐引擎为用户推荐的电影列表。

首先,展示一下基于用户的推荐引擎的推荐结果,推荐引擎会根据用户已打分的电影找到用户的“邻居”,将“邻居”们比较喜欢的电影推荐给当前用户。
图 5. 基于用户的推荐结果(查看大图
图 5. 基于用户的推荐结果
其次,图 6 展示了基于内容的推荐引擎的推荐结果,推荐引擎会根据用户已打分的电影找到相似的电影,推荐给当前用户。
图 6. 基于内容的推荐结果(查看大图
图 6. 基于内容的推荐结果
最后,展示 SlopeOne 推荐引擎的推荐结果,这种推荐引擎计算速度较快,效果很好,是一种非常快速简单的基于项目的推荐方法。
图 7. SlopeOne 实现的推荐结果(查看大图
图 7. SlopeOne 实现的推荐结果
总结

目前几乎所有大型的电子商务系统,都不同程度地使用了各种形式的推荐引擎。推荐技术的使用,不仅大大的提高了用户购物的体验,增加了用户的粘着度,而且电子商务公司也由于推荐系统的应用而大大的提高了交叉销售的可能,从而大大的提高了营业额。今天,你有自己的商品推荐系统么?

借鉴于电子商务的成功经验,我们可以把推荐技术应用到其他的领域。像我们在文章中所演示的那样,你可以创建一个电影的推荐引擎。如果你是一个 blogger,那么你可以创建一个博客的推荐引擎,如果你是一个新闻提供商,你可以使用推荐技术为不同的用户推荐它可能关心的新闻,等等。

今天,你推荐了么?
下载

描述 名字 大小 下载方法
本文示例代码 src.zip 14 MB HTTP

关于下载方法的信息
参考资料

  • Apache Mahout 简介” (Grant Ingersoll,developerWorks,2009 年 10 月):Mahout 的创始者 Grant Ingersoll 介绍了机器学习的基本概念,并演示了如何使用 Mahout 来实现文档集群、提出建议和组织内容。
  • Apache Mahout:Apache Mahout 项目的主页,搜索关于 Mahout 的所有内容。
  • Taste Documentation:Taste 的介绍文档,阅读 Taste 文档。
  • GroupLens:从 GroupLens 项目获取真实的电影评分数据。
  • 机器学习:机器学习的 Wikipedia 页面,可帮助您了解关于机器学习的更多信息。
  • developerWorks Java 技术专区:数百篇关于 Java 编程各个方面的文章。

作者简介

赵晨婷,现就职于 IBM 中国软件开发中心 Web 2.0 开发小组,对 SOA、J2EE、Web 2.0 应用的开发有丰富的经验。主要关注点在数据处理、数据搜索、推荐算法和推荐系统设计等。

马春娥,工作在 IBM 中国软件开发中心 Web 2.0 开发小组,开发人员,曾参与 Project Zero 和 Lotus Mashup Center 的开发。主要的关注点在 Web 2.0 领域的数据的建模,数据的处理,数据的可视化,Web2.0 领域的数据的语义,数据的关联等。

建议

iReader iReader Logo

0 条评论

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注