转载请注明出处:http://blog.csdn.net/gamer_gyt
博主微博:http://weibo.com/234654758
Github:https://github.com/thinkgamer
参考:
Mahout推荐算法API详解
Mahout的taste推荐系统里的几种Recommender分析
前言:Mahout框架集成了大量的常用的机器学习算法,且都支持在Hadoop分布式环境下运行,很大程度上节约了数据处理的时间成本,其中的推荐算法引擎有cf.taste包实现,它提供了一套完整的推荐算法工具库,同时规范了数据结构,并标准了程序开发过程。
1:Mahout推荐算法介绍
2:Taste接口相关介绍
3:单机内存算法实现
4:基于hadoop分布式算法的实现
5:算法评判标准
一:Mahout推荐算法介绍
我们先看看一下org.apache.mahout.cf.taste如下图所示
packages的说明:
common:公共类包括,异常,数据刷新接口,权重常量
eval:定义构造器接口,类似于工厂模式(什么是工厂模式请参考:http://blog.chinaunix.net/uid-25958655-id-4243289.html)
model:定义数据类型接口
neighborhood:定义近邻算法的接口
recommender:定义推荐算法的接口
similarity:定义相似度算法接口
transforms:定义数据转换接口
hadoop:基于hadoop的分布式算法的实现类
impl:单机内存算法实现类
从上面的packages情况来看,可以粗略的看出推荐引擎分为5个主要部分组成:数据模型,相似度算法,近邻算法,推荐算法,算法评分器
从数据处理能力上看,算法可以分为:单机内存算法,基于hadoop的分布式算法
二:Taste接口相关介绍
Mahout使用了Taste来提交协同过滤算法的实现,它是一个基于Java实现的可扩展的,高效的推荐系统,Taste既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法,同时,Taste不仅仅只适用于Java应用程序,它可以作为内部服务器的一个组件以HTTP和Web Service的形式向外界提供推荐的逻辑,Taste的设计使它能满足企业对推荐引擎在性能,灵活性和可扩展性等方面的要求。
Taste主要包括以下几个接口:
DataModel
是用户喜好信息的抽象接口,它的具体实现支持从任意类型的数据源抽取用户喜好信息。Taste 默认提供 JDBCDataModel 和 FileDataModel,分别支持从数据库和文件中读取用户的喜好信息。UserSimilarity
和ItemSimilarity
。UserSimilarity 用于定义两个用户间的相似度,它是基于协同过滤的推荐引擎的核心部分,可以用来计算用户的“邻居”,这里我们将与当前用户口味相似的用户称为他的邻居。ItemSimilarity 类似的,计算内容之间的相似度。UserNeighborhood
用于基于用户相似度的推荐方法中,推荐的内容是基于找到与当前用户喜好相似的邻居用户的方式产生的。UserNeighborhood 定义了确定邻居用户的方法,具体实现一般是基于 UserSimilarity 计算得到的。Recommender
是推荐引擎的抽象接口,Taste 中的核心组件。程序中,为它提供一个 DataModel,它可以计算出对不同用户的推荐内容。实际应用中,主要使用它的实现类 GenericUserBasedRecommender 或者 GenericItemBasedRecommender,分别实现基于用户相似度的推荐引擎或者基于内容的推荐引擎。RecommenderEvaluator
:评分器。RecommenderIRStatsEvaluator
:搜集推荐性能相关的指标,包括准确率、召回率等等。
目前,Mahout为DataModel提供了以下几种实现:
- org.apache.mahout.cf.taste.impl.model.GenericDataModel
- org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel
- org.apache.mahout.cf.taste.impl.model.PlusAnonymousUserDataModel
- org.apache.mahout.cf.taste.impl.model.file.FileDataModel
- org.apache.mahout.cf.taste.impl.model.hbase.HBaseDataModel
- org.apache.mahout.cf.taste.impl.model.cassandra.CassandraDataModel
- org.apache.mahout.cf.taste.impl.model.mongodb.MongoDBDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.SQL92JDBCDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.PostgreSQLJDBCDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.GenericJDBCDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.SQL92BooleanPrefJDBCDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.MySQLBooleanPrefJDBCDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.PostgreBooleanPrefSQLJDBCDataModel
- org.apache.mahout.cf.taste.impl.model.jdbc.ReloadFromJDBCDataModel
从类名上就可以大概猜出来每个DataModel的用途,奇怪的是竟然没有HDFS的DataModel,有人实现了一个,请参考 MAHOUT-1579 。
UserSimilarity
和 ItemSimilarity
相似度实现有以下几种:
CityBlockSimilarity
:基于Manhattan距离相似度EuclideanDistanceSimilarity
:基于欧几里德距离计算相似度LogLikelihoodSimilarity
:基于对数似然比的相似度PearsonCorrelationSimilarity
:基于皮尔逊相关系数计算相似度SpearmanCorrelationSimilarity
:基于皮尔斯曼相关系数相似度TanimotoCoefficientSimilarity
:基于谷本系数计算相似度UncenteredCosineSimilarity
:计算 Cosine 相似度
以上相似度的说明,请参考Mahout推荐引擎介绍。
UserNeighborhood 主要实现有两种:
- NearestNUserNeighborhood:对每个用户取固定数量N个最近邻居
- ThresholdUserNeighborhood:对每个用户基于一定的限制,取落在相似度限制以内的所有用户为邻居
Recommender分为以下几种实现:
- GenericUserBasedRecommender:基于用户的推荐引擎
- GenericBooleanPrefUserBasedRecommender:基于用户的无偏好值推荐引擎
- GenericItemBasedRecommender:基于物品的推荐引擎
- GenericBooleanPrefItemBasedRecommender:基于物品的无偏好值推荐引擎
RecommenderEvaluator有以下几种实现:
AverageAbsoluteDifferenceRecommenderEvaluator
:计算平均差值RMSRecommenderEvaluator
:计算均方根差
RecommenderIRStatsEvaluator的实现类是GenericRecommenderIRStatsEvaluator。
三:单机内存算法实现
Mahout推荐算法API详解
单机算法实现:就是在单机环境下运行的算法,是由cf.taste项目实现的,象我们熟悉的User_CF,Item_CF都是支持单机运行的,并且参数可以灵活配置,单机算法实现的实例如下:
测试数据集如下:/home/thinkgamer/test.txt
单机算法实现参考:
1,101,5
1,102,3
1,103,2.5
2,101,2
2,102,2.5
2,103,5
2,104,2
3,101,2.5
3,104,4
3,105,4.5
3,107,5
4,101,5
4,103,3
4,104,4.5
4,106,4
5,101,4
5,102,3
5,103,2
5,104,4
5,105,3.5
5,106,4
实现的代码如下:
-
package tuijian_alone;
-
-
import java.io.*;
-
import java.util.*;
-
import org.apache.mahout.cf.taste.common.TasteException;
-
import org.apache.mahout.cf.taste.impl.model.file.*;
-
import org.apache.mahout.cf.taste.impl.neighborhood.*;
-
import org.apache.mahout.cf.taste.impl.recommender.*;
-
import org.apache.mahout.cf.taste.impl.recommender.slopeone.SlopeOneRecommender;
-
import org.apache.mahout.cf.taste.impl.similarity.*;
-
import org.apache.mahout.cf.taste.model.*;
-
import org.apache.mahout.cf.taste.neighborhood.*;
-
import org.apache.mahout.cf.taste.recommender.*;
-
import org.apache.mahout.cf.taste.similarity.*;
-
-
-
public class tuijian_alone {
-
// private TestMahout(){};
-
-
-
public static void main(String args[]) throws Exception {
-
-
tuijian_alone testMahout = new tuijian_alone();
-
System.out.println("The baseUserCF Result:");
-
testMahout.baseUserCF();
-
System.out.println("The baseItemCF Result:");
-
testMahout.baseItemCF();
-
System.out.println("The baseSlopOne Result:");
-
testMahout.baseSlopOne();
-
}
-
//基于用户相似度的协同过滤推荐实现
-
public void baseUserCF(){
-
try {
-
// 1,构建模型
-
DataModel dataModel = new FileDataModel(new File("../test.txt"));
-
//2,计算相似度
-
UserSimilarity userSimilarity = new PearsonCorrelationSimilarity(dataModel);
-
//3,查找K近邻
-
UserNeighborhood userNeighborhood = new NearestNUserNeighborhood(2, userSimilarity, dataModel);
-
//4,构造推荐引擎
-
Recommender recommender = new GenericUserBasedRecommender(dataModel, userNeighborhood, userSimilarity);
-
//为用户i推荐2个item
-
for(int i=1;i<6;i++){
-
System.out.println("recommand for user:" + i);
-
List recommendations = recommender.recommend(i, 2);
-
for (RecommendedItem recommendation:recommendations){
-
System.out.println(recommendation);
-
}
-
}
-
}catch(IOException e){
-
e.printStackTrace();
-
}catch(TasteException e){
-
e.printStackTrace();
-
}
-
}
-
-
//基于内容相似度的协同过滤推荐实现
-
public void baseItemCF(){
-
DataModel model;
-
try {
-
model = new FileDataModel(new File("../test.txt"));
-
ItemSimilarity itemsimilarity =new PearsonCorrelationSimilarity(model);
-
Recommender recommender= new GenericItemBasedRecommender(model,itemsimilarity);
-
List recommendations =recommender.recommend(1, 4);
-
for(RecommendedItem recommendation :recommendations){
-
System.out.println(recommendation);
-
}
-
} catch (IOException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
} catch (TasteException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
-
}
-
//基于SlopOne的推荐实现
-
public void baseSlopOne(){
-
DataModel model;
-
try {
-
model = new FileDataModel(new File("/home/thinkgamer/Java/hadoop_shizhan/src/tuijian_alone/test.txt"));
-
Recommender recommender= new SlopeOneRecommender(model);
-
List recommendations =recommender.recommend(1, 4);
-
for(RecommendedItem recommendation :recommendations){
-
System.out.println(recommendation);
-
}
-
} catch (IOException e) {
-
// TODO Auto-generated catch block
-
System.out.println("Io Error");
-
e.printStackTrace();
-
} catch (TasteException e) {
-
// TODO Auto-generated catch block
-
System.out.println("Taste Error");
-
e.printStackTrace();
-
}
-
-
}
-
-
}
运行结果如下图所示:
单机内存算法的问题在于:受限于单机的资源,对于中等规模的数据,有能力计算,但是超过100G的数据对于单机来说是不可能完成的任务
四:基于Hadoop分布式算法实现
基于hadoop分布式算法的实现,就是把单机内存算法并行优化,把任务分散到多个计算机上一起运行,Mahout提供了基于ItemCFhadoop并行化算法实现,基于hadoop分布式算法实现参考:Mahout分步式程序开发 基于物品的协同过滤ItemCF
分布式算法的问题在于,如何让单机算法并行化,在单机算法中,我们只需要考虑算法,数据结构,内存,CPU就够了,但是分布式算法还要额外考虑很多情况,比如多结点的数据合并,数据排序,网络通信故障,节点宕机重算,数据分布式存储等等很多问题
并行化算法实现参考:用Mahout构建职位推荐引擎
五:算法评判标准:召回率(recall)与查准率(precision)
Mahout提供了2个评估推荐器的指标,查准率和召回率(查全率),这两个指标是搜索引擎中经典的度量方法。
-
相关 不相关
-
检索到 A C
-
未检索到 B D
- A:检索到的,相关的 (搜到的也想要的)
- B:未检索到的,但是相关的 (没搜到,然而实际上想要的)
- C:检索到的,但是不相关的 (搜到的但没用的)
- D:未检索到的,也不相关的 (没搜到也没用的)
被检索到的越多越好,这是追求“查全率”,即A/(A+B),越大越好。
被检索到的,越相关的越多越好,不相关的越少越好,这是追求“查准率”,即A/(A+C),越大越好。
在大规模数据集合中,这两个指标是相互制约的。当希望索引出更多的数据的时候,查准率就会下降,当希望索引更准确的时候,会索引更少的数据。