Mahout推荐的ItemBased

一、   算法原理

(一)    基本的

下面的例子,参见图评分矩阵:表现user,归类为item.

图(1)

该算法的原理:

1.  计算Item之间的相似度。

2.  对用户U做推荐

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVleWVkZWFp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

公式(一)

Map tmp ;

Map tmp1 ;

for(item a  in userRatedItems){

rate  =userforItemRate(a)

ListsimItem =getSimItem(a);

For(Jin simItem){

Item b =j;

Simab=sim(a,b);

Tmp.add(b,Tmp .get(b)+simab*rate)

tmp1.add(b, tmp1.get(b)+simab)

}

}

Maptmp2=temp/temp1

Sortbyval(tmp2)

return topK(tmp2,k)

(二)    相似度计算

1.  Cos相似度

公式(二)

2.  皮尔逊相似度

公式(三)

3.  调整的cos相似度

公式(四)

(三)    採样

计算全量的itemPair之间的相似度耗费大量的时间。也是没有必要的,所以须要採样,减小计算量。

二、   单机模式实现

(一)    候选Item搜索

计算全部Item Pair之间的相似度在单机模式下是不现实的,须要在海量的候选集中搜索出一部分最有可能的候选集用于计算。

Mahout提供了4中候选Item选择策略。

1.  AllSimilarItemsCandidateItemsStrategy

@Override

FastIDSet doGetCandidateItems(long[] preferredItemIDs, DataModel dataModel) throws TasteException {

FastIDSet candidateItemIDs = new FastIDSet();

for (long itemID : preferredItemIDs) {

candidateItemIDs.addAll(similarity.allSimilarItemIDs(itemID));

}

candidateItemIDs.removeAll(preferredItemIDs);

return candidateItemIDs;

}

2.  AllUnknownItemsCandidateItemsStrategy

@Override

protected FastIDSet doGetCandidateItems(long[] preferredItemIDs, DataModel dataModel) throws TasteException {

FastIDSet possibleItemIDs = new FastIDSet(dataModel.getNumItems());

LongPrimitiveIterator allItemIDs = dataModel.getItemIDs();

while (allItemIDs.hasNext()) {

possibleItemIDs.add(allItemIDs.nextLong());

}

possibleItemIDs.removeAll(preferredItemIDs);

return possibleItemIDs;

}

3.  PreferredItemsNeighborhoodCandidateItemsStrategy

@Override

protected FastIDSet doGetCandidateItems(long[] preferredItemIDs, DataModel dataModel) throws TasteException {

FastIDSet possibleItemsIDs = new FastIDSet();

for (long itemID : preferredItemIDs) {

PreferenceArray itemPreferences = dataModel.getPreferencesForItem(itemID);

int numUsersPreferringItem = itemPreferences.length();

for (int index = 0; index < numUsersPreferringItem; index++) {

possibleItemsIDs.addAll(dataModel.getItemIDsFromUser(itemPreferences.getUserID(index)));

}

}

possibleItemsIDs.removeAll(preferredItemIDs);

return possibleItemsIDs;

}

4.  SamplingCandidateItemsStrategy

private static int computeMaxFrom(int factor, int numThings) {

if (factor == NO_LIMIT_FACTOR) {

return MAX_LIMIT;

}

long max = (long) (factor * (1.0 + Math.log(numThings) / LOG2));

return max > MAX_LIMIT ? MAX_LIMIT : (int) max;

}

@Override

protected FastIDSet doGetCandidateItems(long[] preferredItemIDs, DataModel dataModel) throws TasteException {

LongPrimitiveIterator preferredItemIDsIterator = new LongPrimitiveArrayIterator(preferredItemIDs);

if (preferredItemIDs.length > maxItems) {

double samplingRate = (double) maxItems / preferredItemIDs.length;

//      log.info("preferredItemIDs.length {}, samplingRate {}", preferredItemIDs.length, samplingRate);

preferredItemIDsIterator =

new SamplingLongPrimitiveIterator(preferredItemIDsIterator, samplingRate);

}

FastIDSet possibleItemsIDs = new FastIDSet();

while (preferredItemIDsIterator.hasNext()) {

long itemID = preferredItemIDsIterator.nextLong();

PreferenceArray prefs = dataModel.getPreferencesForItem(itemID);

int prefsLength = prefs.length();

if (prefsLength > maxUsersPerItem) {

Iterator<Preference> sampledPrefs =

new FixedSizeSamplingIterator<Preference>(maxUsersPerItem, prefs.iterator());

while (sampledPrefs.hasNext()) {

addSomeOf(possibleItemsIDs, dataModel.getItemIDsFromUser(sampledPrefs.next().getUserID()));

}

} else {

for (int i = 0; i < prefsLength; i++) {

addSomeOf(possibleItemsIDs, dataModel.getItemIDsFromUser(prefs.getUserID(i)));

}

}

}

possibleItemsIDs.removeAll(preferredItemIDs);

return possibleItemsIDs;

}

private void addSomeOf(FastIDSet possibleItemIDs, FastIDSet itemIDs) {

if (itemIDs.size() > maxItemsPerUser) {

LongPrimitiveIterator it =

new SamplingLongPrimitiveIterator(itemIDs.iterator(), (double) maxItemsPerUser / itemIDs.size());

while (it.hasNext()) {

possibleItemIDs.add(it.nextLong());

}

} else {

possibleItemIDs.addAll(itemIDs);

}

}

(二)    估值

protected float doEstimatePreference(long userID, PreferenceArray preferencesFromUser, long itemID)

throws TasteException {

double preference = 0.0;

double totalSimilarity = 0.0;

int count = 0;

double[] similarities = similarity.itemSimilarities(itemID, preferencesFromUser.getIDs());

for (int i = 0; i < similarities.length; i++) {

double theSimilarity = similarities[i];

if (!Double.isNaN(theSimilarity)) {

// Weights can be negative!

preference += theSimilarity * preferencesFromUser.getValue(i);

totalSimilarity += theSimilarity;

count++;

}

}

// Throw out the estimate if it was based on no data points, of course, but also if based on

// just one. This is a bit of a band-aid on the 'stock' item-based algorithm for the moment.

// The reason is that in this case the estimate is, simply, the user's rating for one item

// that happened to have a defined similarity. The similarity score doesn't matter, and that

// seems like a bad situation.

if (count <= 1) {

return Float.NaN;

}

float estimate = (float) (preference / totalSimilarity);

if (capper != null) {

estimate = capper.capEstimate(estimate);

}

return estimate;

}

(三)    推荐

1.  依据历史评分列表推荐

这样的推荐方式依据用户之前产生过评分的item做推荐。推荐结果依照预计值的大小排序。

@Override

public List<RecommendedItem> recommend(long userID,
int howMany, IDRescorer rescorer) throws TasteException {

Preconditions.checkArgument(howMany >= 1, "howMany must be at least 1");

log.debug("Recommending items for user ID '{}'", userID);

PreferenceArray preferencesFromUser = getDataModel().getPreferencesFromUser(userID);

if (preferencesFromUser.length() == 0) {

return Collections.emptyList();

}

FastIDSet possibleItemIDs = getAllOtherItems(userID, preferencesFromUser);

TopItems.Estimator<Long> estimator = new Estimator(userID, preferencesFromUser);

List<RecommendedItem> topItems = TopItems.getTopItems(howMany, possibleItemIDs.iterator(), rescorer,

estimator);

log.debug("Recommendations are: {}", topItems);

return topItems;

}

2.  Because推荐

这样的推荐方式用于实时推荐。

@Override

public List<RecommendedItem> recommendedBecause(long userID, long itemID, int howMany) throws TasteException {

Preconditions.checkArgument(howMany >= 1, "howMany must be at least 1");

DataModel model = getDataModel();

TopItems.Estimator<Long> estimator = new RecommendedBecauseEstimator(userID, itemID);

PreferenceArray prefs = model.getPreferencesFromUser(userID);

int size = prefs.length();

FastIDSet allUserItems = new FastIDSet(size);

for (int i = 0; i < size; i++) {

allUserItems.add(prefs.getItemID(i));

}

allUserItems.remove(itemID);

return TopItems.getTopItems(howMany, allUserItems.iterator(), null, estimator);

}

//估值方法

@Override

public double estimate(Long itemID) throws TasteException {

Float pref = getDataModel().getPreferenceValue(userID, itemID);

if (pref == null) {

return Float.NaN;

}

double similarityValue = similarity.itemSimilarity(recommendedItemID, itemID);

return (1.0 + similarityValue) * pref;

}

三、   MapReduce模式实现

(一)    将偏好文件转换成评分矩阵(PreparePreferenceMatrixJob)

(二)    计算共现矩阵相似度(RowSimilarityJob)

(三)    挑选最相似的K个Item

(四)    用户偏好向量和相似降维后的共现矩阵做乘法

(五)    过滤制定的user\titem

(六)    生成终于的推荐结果

四、   实例演示

1.  单机模式

1)  批量推荐

DataModel  dataModel =
new FileDataModel(new File("p/pereference"));

ItemSimilarity  similarity  = new PearsonCorrelationSimilarity(dataModel);

ItemBasedRecommender  recommender = new GenericItemBasedRecommender(dataModel,similarity );

System.out.println(recommender.recommend(10, 10));

2)  Because推荐

DataModel  dataModel = new FileDataModel(new File("p/pereference"));

ItemSimilarity  similarity  = new PearsonCorrelationSimilarity(dataModel);

ItemBasedRecommender  recommender = new GenericItemBasedRecommender(dataModel,similarity );

System.out.println(recommender.recommendedBecause(10, 10328, 100));

2.  MapReduce模式

API

org.apache.mahout.cf.taste.hadoop.item.RecommenderJob.main(args)

--input

偏好数据路径,文本文件。

格式 userid\t itemid\t preference

--output

推荐结果路径

-- numRecommendations

推荐个数

--usersFile

须要做出推荐的user,默认所有做推荐

--itemsFile

须要做出推荐的item,默认所有做推荐

--filterFile

文件格式文本。userid\itemid 。目的是给userid的用户不要推荐itemid的item

--booleanData

是否是布尔数据

--maxPrefsPerUser

最大偏好值

--minPrefsPerUser

最小偏好值

--maxSimilaritiesPerItem

给每个Item计算最多的相似item数目

--maxPrefsPerUserInItemSimilarity

ItemSimilarity预计item相似度时,对每个user最多偏好数目

--similarityClassname

SIMILARITY_PEARSON_CORRELATION、SIMILARITY_COOCCURRENCE、SIMILARITY_LOGLIKELIHOOD、SIMILARITY_TANIMOTO_COEFFICIENT、SIMILARITY_CITY_BLOCK、SIMILARITY_COSINE、SIMILARITY_EUCLIDEAN_DISTANCE

--threshold

删除低于该阈值的item对

--outputPathForSimilarityMatrix

指定生成的item相似矩阵路径,文本文件,格式为 itemA \t itemB \t 相似值

实例

String  [] args ={"--input","p",

"--output","recommender",

"--numRecommendations","10",

"--outputPathForSimilarityMatrix","simMatrix",

"--similarityClassname","SIMILARITY_PEARSON_CORRELATION"}

org.apache.mahout.cf.taste.hadoop.item.RecommenderJob.main(args);

五、   參考文献

1.  M.Deshpandeand G. Karypis. Item-based top-n recommendation algorithms.

2.  B.M.Sarwar, G. Karypis, J.A. Konstan, and J. Reidl. Item-based collaborativefiltering recommendation algorithms.

3.  Item-based collaborative filtering

4.  Accuratelycomputing running variance

版权声明:本文博主原创文章,博客,未经同意不得转载。

Mahout推荐算法ItemBased的更多相关文章

  1. Mahout推荐算法之ItemBased

    Mahout推荐之ItemBased 一.   算法原理 (一)    基本原理 如下图评分矩阵所示:行为user,列为item. 图(1) 该算法的原理: 1.  计算Item之间的相似度. 2.  ...

  2. Mahout推荐算法API详解

    转载自:http://blog.fens.me/mahout-recommendation-api/ Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, ...

  3. Mahout推荐算法基础

    转载自(http://www.geek521.com/?p=1423) Mahout推荐算法分为以下几大类 GenericUserBasedRecommender 算法: 1.基于用户的相似度 2.相 ...

  4. 转】Mahout推荐算法API详解

    原博文出自于: http://blog.fens.me/mahout-recommendation-api/ 感谢! Posted: Oct 21, 2013 Tags: itemCFknnMahou ...

  5. Mahout推荐算法之SlopOne

    Mahout推荐算法之SlopOne 一.       算法原理 有别于基于用户的协同过滤和基于item的协同过滤,SlopeOne采用简单的线性模型估计用户对item的评分.如下图,估计UserB对 ...

  6. [转]Mahout推荐算法API详解

    Mahout推荐算法API详解 Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeepe ...

  7. Mahout推荐算法API具体解释【一起学Mahout】

    阅读导读: 1.mahout单机内存算法实现和分布式算法实现分别存在哪些问题? 2.算法评判标准有哪些? 3.什么会影响算法的评分? 1. Mahout推荐算法介绍 Mahout推荐算法,从数据处理能 ...

  8. 从源代码剖析Mahout推荐引擎

    转载自:http://blog.fens.me/mahout-recommend-engine/ Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pi ...

  9. 转】从源代码剖析Mahout推荐引擎

    原博文出自于: http://blog.fens.me/mahout-recommend-engine/ 感谢! 从源代码剖析Mahout推荐引擎 Hadoop家族系列文章,主要介绍Hadoop家族产 ...

随机推荐

  1. Apache Commons IO入门教程(转)

    Apache Commons IO是Apache基金会创建并维护的Java函数库.它提供了许多类使得开发者的常见任务变得简单,同时减少重复(boiler-plate)代码,这些代码可能遍布于每个独立的 ...

  2. C++中的#pragma 预处理指令详解

    源地址:http://blog.csdn.net/roger_77/article/details/660311 在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态 ...

  3. MVC应用程序与单选列表

    原文:MVC应用程序与单选列表 前几天,Insus.NET有在MVC应用程序中,练习了<MVC应用程序,动态创建单选列表(RadioButtonList)>http://www.cnblo ...

  4. CC 3-Palindromes(manacher)

    传送门:3-Palindromes 题意:求为回文串且能整除3且不前导0的子串个数. 分析:由 manacher算法O(N)可算出以i为坐标的最长为p[i]回文子串,且Si-k,Si-k+1..... ...

  5. SVNKIT操作SVN版本库的完整例子

    Model: package com.wjy.model; public class RepositoryInfo { public static String storeUrl="http ...

  6. UVa 1292 - Strategic game (树形dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接: 点击打开链接 题目大意 给定一棵树,选择尽量少的节点,使得每个没有选中的结点至少和一个已选结点相邻. 思路 ...

  7. MySQL将表a中查询的数据插入到表b中

    MySQL将表a中查询的数据插入到表b中 假设表b存在 insert into b select * from a; 假设表b不存在 create table b as select * from a ...

  8. HttpApplication处理对象与HttpModule处理模块

    HttpApplication处理对象与HttpModule处理模块 (第三篇) 一.HttpApplication对象简述 在HttpRuntime创建了HttpContext对象之后,HttpRu ...

  9. Knockout应用开发指南 第五章:创建自定义绑定

    原文:Knockout应用开发指南 第五章:创建自定义绑定 创建自定义绑定 你可以创建自己的自定义绑定 – 没有必要非要使用内嵌的绑定(像click,value等).你可以你封装复杂的逻辑或行为,自定 ...

  10. linux--档案权限与目录配置

    下面是最近学习档案权限与目录配置的一些知识点总结***博客园-邦邦酱好*** Linux最优秀的地方之一,就在于他的多人多任务环境.而为了让各个使用者具有较保密的档案数据,因此档案的权限管理就变的很重 ...