目录
6.2、UserSimilarity 和 ItemSimilarity(相似度) 接口
6.5、RecommenderEvaluator(推荐系统评测)接口
0、相关文章链接
1、推荐系统
1.1、什么是推荐系统
为了解决信息过载和用户无明确需求的问题,找到用户感兴趣的物品,才有了个性化推荐系统。
1.2、推荐系统业务流程
推荐系统广泛存在于各类网站中,作为一个应用为用户提供个性化的推荐。它需要一些用户的历史数据,一般由三个部分组成:基础数据、推荐算法系统、前台展示。
-
基础数据包括很多维度,包括用户的访问、浏览、下单、收藏,用户的历史订单信息,评价信息等很多信息;
-
推荐算法系统主要是根据不同的推荐诉求由多个算法组成的推荐模型;
-
前台展示主要是对客户端系统进行响应,返回相关的推荐信息以供展示。
2、协同过滤算法
2.1、协同过滤算法概述
迄今为止,在个性化推荐系统中,协同过滤技术是应用最成功的技术。目前国内外有许多大型网站应用这项技术为用户更加智能(个性化、千人千面)的推荐内容。
-
核心思想:协同过滤一般是在海量的用户中发掘出一小部分和你品位比较类似的,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的其他东西组织成一个排序的目彔作为推荐给你。
-
问题:如何确定一个用户是丌是和你有相似的品位?如何将邻居们的喜好组织成一个排序的目彔?
2.2、如何选择?
-
在社交项目中,如微信、QQ,显然选择基于用户推荐比较好,因为推荐往往都是和人相关的。
-
如:在QQ登录后,会有提示,好友的好友可能是你认识的,推荐给你添加好友。
-
-
在电商项目中,用户的数量远大于商品数量,所以基于商品的推荐的复杂度要低,而且也比较合理。
-
其实,在实际的推荐系统中,往往不单是使用一种推荐,而是会多种推荐混合使用。
-
所以,选择基于用户还是基于商品的推荐,和应用场景有很大的关系。
3、相似度算法
无论是基于用户还是基于商品的推荐,都是需要找到相似的用户或者商品,才能做推荐,所以,相似度算法就变得非常重要了。
常见的相似度算法有:
-
欧几里德距离算法(Euclidean Distance)
-
皮尔逊相似度算法(Pearson Correlation Coefficient)
-
基于夹角余弦相似度算法(Consine Similarity)
-
基于Tanimoto系数相似度(Tanimoto Coefficient)
4、最近邻域
通过相似度计算,可以计算出邻居,问题来了,我们如果选取出几个邻居作为参考,进行推荐呢?
通常有2种方式:
-
固定数量的邻居:K-neighborhoods
-
基于相似度门槛的邻居:Threshold-based neighborhoods
5、Mahout的概述
Mahout使用了Taste来提高协同过滤算法的实现,它是一个基于Java实现的可扩展的,高效的推荐引擎。Taste既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法。同时,Taste不仅仅只适用于Java应用程序,它可以作为内部服务器的一个组件以HTTP和Web Service的形式向外界提供推荐的逻辑。Taste的设计使它能满足企业对推荐引擎在性能、灵活性和可扩展性等方面的要求。
5.1、Mahout的起源
-
2008年成为Lucene的子项目,Lucene作为搜索引擎项目,存在很多文本数据分析和挖掘的需求(例如文本重复判断,文本自动分类等等),导致Lucene项目中部分开发者转向机器学习领域研究算法,最终这些机器学习算法形成最初的Mahout
-
吸收开源协同过滤算法项目Taste
-
2010年成为Apache顶级项目
5.2、Mahout的能做什么
- Mahout提供了基于用户和基于商品的推荐系统的协同过滤算法;
- 提供常用的相似度算法,如:欧几里得距离算法、皮尔逊相似度算法等;
- Mahout提供了2种最近邻域的实现;
- Mahout提供了多种数据源实现,可以读取文件、数据库、Hbase等;
6、Taste 中的主要接口
6.1、DataModel(数据模块)接口
DataModel 是用户喜好信息的抽象接口,它的具体实现支持从任意类型的数据源抽取用户喜好信息。Taste 默认提供 JDBCDataModel 和 FileDataModel,分别支持从数据库和文件中读取用户的喜好信息。
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
6.2、UserSimilarity 和 ItemSimilarity(相似度) 接口
UserSimilarity 和 ItemSimilarity 。UserSimilarity 用于定义两个用户间的相似度,它是基于协同过滤的推荐引擎的核心部分,可以用来计算用户的“邻居”,这里我们将与当前用户口味相似的用户称为他的邻居。ItemSimilarity 类似的,计算Item之间的相似度。
UserSimilarity 和 ItemSimilarity 相似度实现有以下几种:
CityBlockSimilarity :基于Manhattan距离相似度
EuclideanDistanceSimilarity :基于欧几里德距离计算相似度
LogLikelihoodSimilarity :基于对数似然比的相似度
PearsonCorrelationSimilarity :基于皮尔逊相关系数计算相似度
SpearmanCorrelationSimilarity :基于皮尔斯曼相关系数相似度
TanimotoCoefficientSimilarity :基于谷本系数计算相似度
UncenteredCosineSimilarity :计算 Cosine 相似度
6.3、UserNeighborhood(最近邻域)接口
UserNeighborhood 用于基于用户相似度的推荐方法中,推荐的内容是基于找到与当前用户喜好相似的邻居用户的方式产生的。UserNeighborhood 定义了确定邻居用户的方法,具体实现一般是基于 UserSimilarity 计算得到的。
UserNeighborhood 主要实现有两种:
NearestNUserNeighborhood:对每个用户取固定数量N个最近邻居
ThresholdUserNeighborhood:对每个用户基于一定的限制,取落在相似度限制以内的所有用户为邻居
6.4、Recommender(推荐引擎)接口
Recommender 是推荐引擎的抽象接口,Taste 中的核心组件。程序中,为它提供一个 DataModel,它可以计算出对不同用户的推荐内容。实际应用中,主要使用它的实现类 GenericUserBasedRecommender 或者 GenericItemBasedRecommender,分别实现基于用户相似度的推荐引擎或者基于内容的推荐引擎。
Recommender分为以下几种实现:
GenericUserBasedRecommender:基于用户的推荐引擎
GenericBooleanPrefUserBasedRecommender:基于用户的无偏好值推荐引擎
GenericItemBasedRecommender:基于物品的推荐引擎
GenericBooleanPrefItemBasedRecommender:基于物品的无偏好值推荐引擎
6.5、RecommenderEvaluator(推荐系统评测)接口
RecommenderEvaluator有以下几种实现:
AverageAbsoluteDifferenceRecommenderEvaluator :计算平均差值
RMSRecommenderEvaluator :计算均方根差
7、Mahout的实现
7.1、实现基于用户的推荐 UserCF
@Test
public void testBaseUser() throws Exception {
String fileName = "user_item.data";
File file = FileUtils.toFile(TestMahout.class.getClassLoader().getResource(fileName));
// 第一步,定义数据模型
DataModel dataModel = new FileDataModel(file);
// 第二步,定义相识度,这里使用的欧几里得
UserSimilarity userSimilarity = new EuclideanDistanceSimilarity(dataModel);
// 第三步,定义最近邻域,这里使用的是固定数量的邻居
UserNeighborhood userNeighborhood = new NearestNUserNeighborhood(10, userSimilarity, dataModel);
long[] longs = userNeighborhood.getUserNeighborhood(1);
for (long aLong : longs) {
System.out.println(aLong);
}
// 第四步,定义推荐器,这里使用的是基于用户的推荐
Recommender recommender = new GenericUserBasedRecommender(dataModel, userNeighborhood, userSimilarity);
LongPrimitiveIterator userIDs = dataModel.getUserIDs();
while (userIDs.hasNext()) {
Long userId = userIDs.next();
List<RecommendedItem> recommendedItemList = recommender.recommend(userId, 4);
StringBuffer sb = new StringBuffer();
for (RecommendedItem item : recommendedItemList) {
sb.append(item.getItemID() + "|"+item.getValue()+",");
}
System.out.println(userId + "-->" + sb);
}
}
7.2、实现基于商品的推荐
@Test
public void testBaseItem() throws Exception {
String fileName = "user_item.data";
File file = FileUtils.toFile(TestMahout.class.getClassLoader().getResource(fileName));
// 第一步,定义数据模型
DataModel dataModel = new FileDataModel(file);
// 第二步,定义相识度,这里使用的欧几里得
ItemSimilarity itemSimilarity = new EuclideanDistanceSimilarity(dataModel);
// 第三步,定义推荐器,这里使用的是基于用户的推荐
Recommender recommender = new GenericItemBasedRecommender(dataModel, itemSimilarity);
LongPrimitiveIterator userIDs = dataModel.getUserIDs();
while (userIDs.hasNext()) {
Long userId = userIDs.next();
List<RecommendedItem> recommendedItemList = recommender.recommend(userId, 2);
StringBuffer sb = new StringBuffer();
for (RecommendedItem item : recommendedItemList) {
sb.append(item.getItemID() + "|"+item.getValue()+",");
}
System.out.println(userId + "-->" + sb);
}
}
7.3、根据用户浏览记录推荐
@Test
public void testBaseItem2() throws Exception {
String fileName = "user_item.data";
File file = FileUtils.toFile(TestMahout.class.getClassLoader().getResource(fileName));
// 第一步,定义数据模型
DataModel dataModel = new FileDataModel(file);
// 第二步,定义相识度,这里使用的欧几里得
ItemSimilarity itemSimilarity = new EuclideanDistanceSimilarity(dataModel);
// 第三步,定义推荐器,这里使用的是基于用户的推荐
GenericItemBasedRecommender recommender = new GenericItemBasedRecommender(dataModel, itemSimilarity);
LongPrimitiveIterator userIDs = dataModel.getUserIDs();
//用户1,正在浏览103商品,进行推荐
Long userId = 1L;
Long itemId = 103L;
List<RecommendedItem> recommendedItemList = recommender.recommendedBecause(userId,itemId,2);
StringBuffer sb = new StringBuffer();
for (RecommendedItem item : recommendedItemList) {
sb.append(item.getItemID() + "|"+item.getValue()+",");
}
System.out.println(userId + "-->" + sb);
}
8、将Mahout提交到hadoop运行
提交到hadoop运行,需要有2步操作:
第一步,将需要计算的数据上传到hdfs
第二步,通过hadoop执行mahout-examples-0.13.0-job.jar中的RecommenderJob类
第三步,在输出结果文件中查看结果
hadoop jar mahout-examples-0.13.0-job.jar org.apache.mahout.cf.taste.hadoop.item.RecommenderJob --input /user_item.data --output /cc -s SIMILARITY_EUCLIDEAN_DISTANCE
参数说明:
--input(path)(-i): 存储用户偏好数据的目录,该目录下可以包含一个或多个存储用户偏好数据的文本文件;
--output(path)(-o): 结算结果的输出目录
--numRecommendations (integer): 为每个用户推荐的item数量,默认为10
--usersFile (path): 指定一个包含了一个或多个存储userID的文件路径,仅为该路径下所有文件包含的userID做推荐计算 (该选项可选)
--itemsFile (path): 指定一个包含了一个或多个存储itemID的文件路径,仅为该路径下所有文件包含的itemID做推荐计算 (该选项可选)
--filterFile (path): 指定一个路径,该路径下的文件包含了[userID,itemID]值对,userID和itemID用逗号分隔。计算结果将不会为user推荐[userID,itemID]值对中包含的item (该选项可选)
--booleanData (boolean): 如果输入数据不包含偏好数值,则将该参数设置为true,默认为false
--maxPrefsPerUser (integer): 在最后计算推荐结果的阶段,针对每一个user使用的偏好数据的最大数量,默认为10
--minPrefsPerUser (integer): 在相似度计算中,忽略所有偏好数据量少于该值的用户,默认为1
--maxSimilaritiesPerItem (integer): 针对每个item的相似度最大值,默认为100
--maxPrefsPerUserInItemSimilarity (integer): 在item相似度计算阶段,针对每个用户考虑的偏好数据最大数量,默认为1000
--similarityClassname (classname)(-s): 向量相似度计算类
([SIMILARITY_COOCCURRENCE,
SIMILARITY_LOGLIKELIHOOD,
SIMILARITY_TANIMOTO_COEFFICIEN
T, SIMILARITY_CITY_BLOCK,
SIMILARITY_COSINE,
SIMILARITY_PEARSON_CORRELATION
,
SIMILARITY_EUCLIDEAN_DISTANCE]
)
outputPathForSimilarityMatrix:SimilarityMatrix输出目录
--randomSeed:随机种子 –sequencefileOutput:序列文件输出路径
--tempDir (path): 存储临时文件的目录,默认为当前用户的home目录下的temp目录
--startPhase
--endPhase
--threshold (double): 忽略相似度低于该阀值的item对
注:其他相关文章链接由此进 -> 算法文章汇总