基于 mahout 构建社会化推荐引擎.docx
《基于 mahout 构建社会化推荐引擎.docx》由会员分享,可在线阅读,更多相关《基于 mahout 构建社会化推荐引擎.docx(20页珍藏版)》请在冰点文库上搜索。
基于mahout构建社会化推荐引擎
基于ApacheMahout构建社会化推荐引擎
Web2.0的一个核心思想就是“群体智慧”,即基于大众行为,为每个用户提供个性化的推荐。
这使得如何让用户能更快速更准确的获得所需要的信息,成为了Web应用成败的关键。
ApacheMahout是ASF(ApacheSoftwareFoundation)的一个较新的开源项目,提供机器学习领域的一些经典算法的高效实现。
本文主要讲述如何基于ApacheMahout来构建社会化推荐引擎,帮助Web应用开发者更高效的实现个性化推荐功能,从而提高最终用户满意度。
推荐引擎利用特殊的信息过滤(IF,InformationFiltering)技术,将不同的内容(例如电影、音乐、书籍、新闻、图片、网页等)推荐给可能感兴趣的用户。
通常情况下,推荐引擎的实现是通过将用户的个人喜好与特定的参考特征进行比较,并试图预测用户对一些未评分项目的喜好程度。
参考特征的选取可能是从项目本身的信息中提取的,或是基于用户所在的社会或社团环境。
根据如何抽取参考特征,我们可以将推荐引擎分为以下四大类:
∙基于内容的推荐引擎:
它将计算得到并推荐给用户一些与该用户已选择过的项目相似的内容。
例如,当你在网上购书时,你总是购买与历史相关的书籍,那么基于内容的推荐引擎就会给你推荐一些热门的历史方面的书籍。
∙基于协同过滤的推荐引擎:
它将推荐给用户一些与该用户品味相似的其他用户喜欢的内容。
例如,当你在网上买衣服时,基于协同过滤的推荐引擎会根据你的历史购买记录或是浏览记录,分析出你的穿衣品位,并找到与你品味相似的一些用户,将他们浏览和购买的衣服推荐给你。
∙基于关联规则的推荐引擎:
它将推荐给用户一些采用关联规则发现算法计算出的内容。
关联规则的发现算法有很多,如Apriori、AprioriTid、DHP、FP-tree等。
∙混合推荐引擎:
结合以上各种,得到一个更加全面的推荐效果。
随着互联网上数据和内容的不断增长,人们越来越重视推荐引擎在互联网应用中的作用。
可想而知,由于互联网上的数据过多,用户很难找到自己想要的信息,通过提供搜索功能来解决这个问题是远远不够的。
推荐引擎可以通过分析用户的行为来预测用户的喜好,使用户能更容易找到他们潜在需要的信息。
这里以电子商务应用中的推荐引擎为例来说明推荐引擎在互联网应用中的重要性。
电子商务推荐系统(E-CommenceRecommendationSystem)向客户提供商品信息和购买建议,模拟销售人员帮助客户完成购买过程。
智能推荐系统的作用可以概括为:
将电子商务网站的浏览者转变为购买者,提高电子商务网站的交叉销售能力,提高客户对电子商务网站的忠诚度。
电子商务推荐系统的界面表现形式有以下几种:
∙浏览:
客户提出对特定商品的查询要求,推荐引擎根据查询要求返回高质量的推荐;
∙相似商品:
推荐引擎根据客户购物篮中的商品和客户可能感兴趣的商品推荐与它们类似的商品;
∙Email:
推荐系统通过电子邮件的方式通知客户可能感兴趣的商品信息;
∙评论:
推荐系统向客户提供其他客户对相应产品的评论信息。
ApacheMahout是ApacheSoftwareFoundation(ASF)旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。
经典算法包括聚类、分类、协同过滤、进化编程等等,并且,在Mahout的最近版本中还加入了对ApacheHadoop的支持,使这些算法可以更高效的运行在云计算环境中。
Taste简介
Taste是ApacheMahout提供的一个协同过滤算法的高效实现,它是一个基于Java实现的可扩展的,高效的推荐引擎。
Taste既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法。
同时,Taste不仅仅只适用于Java应用程序,它可以作为内部服务器的一个组件以HTTP和WebService的形式向外界提供推荐的逻辑。
Taste的设计使它能满足企业对推荐引擎在性能、灵活性和可扩展性等方面的要求。
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源代码或者例子,需要ApacheAnt1.5+或ApacheMaven2.0.10+。
∙Taste应用程序需要Servlet2.3+容器,例如JakartaTomcat。
∙Taste中的MySQLJDBCDataModel实现需要MySQL4.x+数据库。
安装Taste并运行Demo:
1.从SVN或是下载压缩包得到ApacheMahout的发布版本:
o从SVN获得;
o下载压缩包;
2.从Grouplens下载数据源:
"1MillionMovieLensDataset"。
3.解压数据源压缩包,将movie.dat和ratings.dat拷贝到Mahout安装目录下的taste-web/src/main/resources/org/apache/mahout/cf/taste/example/grouplens目录下。
4.回到在core目录下,运行"mvninstall",将Mahoutcore安装在本地库中。
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的安装目录下,运行"mvnpackage"。
8.运行“mvnjetty:
run-war”。
这里需要将Maven的最大内存设置为1024M,MAVEN_OPTS=-Xmx1024M。
如果需要在Tomcat下运行,可以在执行"mvnpackage"后,将taste-web/target目录下生成的war包拷贝到Tomcat的webapp下,同时也需要将Java的最大内存设置为1024M,JAVA_OPTS=-Xmx1024M,然后启动Tomcat。
9.访问“http:
//localhost:
8080/[your_app]/RecommenderServlet?
userID=1”,得到系统为编号为1的用户的推荐内容。
参看图2,Tastedemo运行结果界面,每一行第一项是推荐引擎预测的评分,第二项是电影的编号。
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.TasteDemo运行结果界面
使用Taste构建推荐引擎实例–电影推荐引擎
根据上面的步骤,我们可以得到一个简单的推荐引擎demo环境,下面介绍如何使用Taste方便地构建自定义的推荐引擎。
抽取Taste工具包
直接使用Mahout的项目环境进行编码,需要使用Ant或者Maven进行编译,整个过程比较复杂,这里我们将构建推荐引擎所需要的工具包从Mahout工程中抽取出来,从而方便的构建自定义的推荐引擎。
在Eclipse中创建Web应用的工程MovieSite,将demo时生成的推荐引擎Web应用的war包解压缩,将lib下的jar文件拷贝到MovieSite的lib目录下。
这样我们就可以方便的编写自己的推荐引擎。
图3.MovieSite工程中引用的jar文件
数据建模
这里我们想要编写一个电影推荐引擎,第一步需要对数据进行建模,分析应用中涉及的主要实体以及实体间的关系,从而设计数据库存储,程序中的类,以及推荐引擎的DataModel。
图4电影和用户信息数据模型
数据模型中存在以下实体:
∙Movie:
表示电影,包含电影的基本信息:
编号、名称、发布时间、类型等等。
∙User:
表示用户,包含用户的基本信息:
编号、姓名、邮件等等。
∙MovieReference:
表示某个用户对某个电影的喜好程度,包含用户编号、电影编号、用户的评分以及评分的时间。
∙MovieSimilarity:
表示两个电影的相似度(这里的相似度是双向的),包括两个电影编号、电影的相似度。
两个电影的相似度可以通过电影的基本信息计算得到。
下面我们就基于这个数据模型设计数据库的存储以及推荐引擎的DataModel。
1.1.创建MySQL数据库存储电影和用户的信息,用户的喜好信息以及电影的相似度。
清单1.创建数据库SQL
CREATEDATABASEmovie;
USEmovie;
CREATETABLEmovies(//保存电影相关的信息。
idINTEGERNOTNULLAUTO_INCREMENT,
namevarchar(100)NOTNULL,
published_yearvarchar(4)defaultNULL,
typevarchar(100)defaultNULL,
--...moremovieinformation...
PRIMARYKEY(id)
);
CREATETABLEusers(//保存用户信息
idINTEGERNOTNULLAUTO_INCREMENT,
namevarchar(50)NOTNULL,
emailvarchar(100)defaultNULL,
--...moreuserinformation...
PRIMARYKEY(id)
);
CREATETABLEmovie_preferences(//保存用户对电影的评分,即喜好程度
userIDINTEGERNOTNULL,
movieIDINTEGERNOTNULL,
preferenceINTEGERNOTNULLDEFAULT0,
timestampINTEGERnotnulldefault0,
FOREIGNKEY(userID)REFERENCESusers(id)ONDELETECASCADE,
FOREIGNKEY(movieID)REFERENCESmovies(id)ONDELETECASCADE
);
CREATETABLEmovie_similarity(//保存电影和电影的相似程度
movieID1INTEGERNOTNULL,
movieID2INTEGERNOTNULL,
similarityDOUBLENOTNULLDEFAULT0,
FOREIGNKEY(movieID1)REFERENCESmovies(id)ONDELETECASCADE,
FOREIGNKEY(movieID2)REFERENCESmovies(id)ONDELETECASCADE
);
CREATEINDEXmovie_preferences_index1ONmovie_preferences(userID,movieID);
CREATEINDEXmovie_preferences_index2ONmovie_preferences(userID);
CREATEINDEXmovie_preferences_index3ONmovie_preferences(movieID);
在实际应用中,我们需要将应用中的实例数据写入到数据库中。
作为例子,这里将从GroupLen下载的数据源写入数据库。
2.设计实现推荐引擎的DataModel。
由于上面采用数据库存储用户的喜好信息,这里需要基于数据库的推荐引擎实现。
这里扩展MySQLJDBCDataModel实现电影推荐引擎的DataModel实例。
清单2.TasteDataModel的实现
publicclassMovieDataModelextendsMySQLJDBCDataModel{
//保存用户对电影的评分的数据库表名
publicfinalstaticStringPERFERENCETABLE="movie_preferences";
publicfinalstaticStringUSERID_COLUMN="userID";//表中用户标识的列名
publicfinalstaticStringITEMID_COLUMN="movieID";//表中电影标识的列名
publicfinalstaticStringPERFERENCE_COLUMN="preference";//表中评分的列名
publicMovieDataModel(StringdataSourceName)throwsTasteException{
super(lookupDataSource(dataSourceName),PERFERENCETABLE,USERID_COLUMN,
ITEMID_COLUMN,PERFERENCE_COLUMN);
}
publicMovieDataModel(){
//DBUtil.getDataSource()将返回应用的数据源
//此应用是J2EE应用,所以这里会采用JDNI的方式创建数据库链接。
super(DBUtil.getDataSource(),PERFERENCETABLE,USERID_COLUMN,
ITEMID_COLUMN,PERFERENCE_COLUMN);
}
}
推荐引擎实现
前面介绍了数据建模和DataModel的实现,下面来详细介绍推荐引擎的实现。
如前面介绍的,Taste既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法。
下面详细介绍如何扩展Taste的推荐引擎接口,实现基于用户相似度的推荐引擎,基于内容相似度的推荐引擎,以及SlopeOne的推荐引擎。
SlopeOne是一种非常快速简单的基于项目的推荐方法,需要使用用户的评分信息。
清单3.基于用户相似度的推荐实现
publicclassUserBasedRecommenderimplementsRecommender{
privatefinalRecommenderrecommender;
publicUserBasedRecommender()throwsIOException,TasteException{
this(newMovieDataModel());
}
publicUserBasedRecommender(DataModelmodel)throwsTasteException{
UserSimilarityuserSimilarity=newPearsonCorrelationSimilarity(model);
userSimilarity.setPreferenceInferrer(newAveragingPreferenceInferrer(model));
UserNeighborhoodneighborhood=
newNearestNUserNeighborhood(3,userSimilarity,model);
recommender=newCachingRecommender(
newGenericUserBasedRecommender(model,neighborhood,userSimilarity));
}
//对外提供的推荐的接口,参数为用户标识和推荐项的个数
publicListrecommend(longuserID,inthowMany)
throwsTasteException{
returnrecommender.recommend(userID,howMany);
}
publicListrecommend(longuserID,inthowMany,
Rescorerrescorer)throwsTasteException{
returnrecommender.recommend(userID,howMany,rescorer);
}
//以下方法都是实现Recommender的接口
publicfloatestimatePreference(longuserID,longitemID)throwsTasteException{
returnrecommender.estimatePreference(userID,itemID);
}
publicvoidsetPreference(longuserID,longitemID,floatvalue)
throwsTasteException{
recommender.setPreference(userID,itemID,value);
}
publicvoidremovePreference(longuserID,longitemID)throwsTasteException{
recommender.removePreference(userID,itemID);
}
publicDataModelgetDataModel(){
returnrecommender.getDataModel();
}
publicvoidrefresh(CollectionalreadyRefreshed){
recommender.refresh(alreadyRefreshed);
}
publicStringtoString(){
return"UserBasedRecommender[recommender:
"+recommender+']';
}
}
从上面的代码示例清单3可以看出,实现一个推荐引擎需要实现Recommender接口,它一般是对于某种Taste提供的推荐引擎的扩展,这是对GenericUserBasedRecommender进行的扩展,其中最重要的方法就是实例化推荐引擎的构造方法,一般其中涉及以下步骤:
∙基于DataModel,计算用户的相似度,这里采用PearsonCorrelation算法。
∙为用户相似度设置相似度推理方法,这里采用了AveragingPreferenceInferrer。
∙基于用户相似度计算用户的“邻居”,这里将与该用户最近距离为3的用户设置为该用户的“邻居”。
∙使用以上得到的用户相似度对象和邻居用户的计算方法对象创建一个GenericUserBasedRecommender的实例。
一般情况下,这时都采用CachingRecommender为RecommendationItem进行缓存,从而提高访问速度。
清单4.基于内容相似度的推荐实现
publicclassItemBasedRecommenderimplementsRecommender{
privatefinalRecommenderrecommender;
publicItemBasedRecommender()throwsIOException,TasteException{
this(newMovieDataModel());
}
publicItemBasedRecommender(DataModeldataModel)throwsTasteException{
Collectioncorrelations=
MovieSimilarityTable.getAllMovieSimila