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. Mac OS提示# 14:自己定义文件图标

    本教程的其余部分再一次错过了方法,和一些使用提示,做一些额外的,我们希望对大家有帮助.  自己定义图标      对于Mac OSX用户来说,Dashboard,Dock栏,壁纸以及各种键盘触摸板的快 ...

  2. Caused by: java.lang.ClassNotFoundException: org.aopalliance.intercept.MethodInterceptor

    org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Fai ...

  3. CentOS6-釋放ip重新分配,centos7 ifconifg没有ip

    http://bbs.csdn.net/topics/390725823 系统win7 ,dhcp自动获取ip虚拟机是10.0 安装之后我装了ubuntu  选用 NAT网络, 刚装完我能上网 ,但是 ...

  4. listview改变选中行字体颜色

    [android]listview改变选中行字体颜色 目标:选中item,其字体设置为#3197FF,未选中的,其字体为#FFFFFF 与listvew设置选中行item背景图片一样,使用select ...

  5. jconsole 连接 eclipse启动项目

    eclipse 启动java项目默认没有开启jmx远程查看功能,假设须要看项目执行的线程内存使用量等信息,能够在eclipse启动參数中添加: -Dcom.sun.management.jmxremo ...

  6. 从iReport至Jaspersoft Studio

    这篇文章同步到http://www.waylau.com/from-ireport-to-jaspersoft-studio/ 从5.5版本号開始,Jaspersoft Studio将代替iRepor ...

  7. Struts工作机制图+OGNL+EL+值栈(Map,对象栈)

    struts 值栈  通过get set方法 方便的获取,设置属性值      比如从jsp页面传来的參数...从Action设置jsp所要回显的内容 注意EL表达式,struts2对request进 ...

  8. HDU4719-Oh My Holy FFF(DP线段树优化)

    Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) T ...

  9. 【iOS】苹果,百度Map定位使用与总结

    iOS中使用较多的3款地图,google地图.百度地图.苹果自带地图(高德).当中苹果自带地图在中国使用的是高德的数据.苹果在iOS 6之后放弃了使用谷歌地图,而改用自家的地图.在国内使用的较多的就是 ...

  10. SCU 2009(数位dp)

    传送门:Zeros and Ones 题意:求总数位为n包含0和1个数相同且整除k的二进制数的个数. 分析:设dp[pos][num][md]表示还有pos位已包含num个1且模k余md的符合条件的二 ...