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. iOS8指纹识别TouchID

    苹果在2014年6月3日的WWDC2014开幕式上推出了新版iOS8系统,界面上iOS8与iOS7相比变化不大,只是在功能方面进行了完好.iOS8通知中心更加强大,支持消息直接回复操作,并支持Quic ...

  2. [翻译]利用C#获取终端服务(Terminal Services)会话的闲置时间

    [翻译]利用C#获取终端服务(Terminal Services)会话的闲置时间 作者:Tuuzed(土仔)   发表于:2008年2月29日版权声明:可以任意转载,转载时请务必以超链接形式标明文章原 ...

  3. 关于智普 - 千人免费学|Python培训|国内最权威python培训|html5

    关于智普 - 千人免费学|Python培训|国内最权威python培训|html5 智普教育隶属于北京顶嵌开源科技有限公司,成立于2008年. 智普开源是基于Linux系统的互联网开源学习平台,讲求务 ...

  4. 对于stackoverflow的中文翻译的相关问题

    我们非常多朋友都给我留言说.希望我翻译一下stackoverflow的问题以及答案,首先我也非常愿意为大家翻译,在能够帮助大家的同一时候,对我本人的技能的提升有优点:可是工作量实在太大,所以我不可能翻 ...

  5. 国内国外MD5在线解密站点

    -http://www.cmd5.com/english.aspx (457,354,352,282) - http://www.md5crack.com - http://www.hashcheck ...

  6. RVDS 3.1 下载地址及破解方法

    RealView Development Suite 3.1  RVDS 3.1下载地址:https://silver.arm.com/download/Development_Tools/RVDS/ ...

  7. Eclipse 改动凝视的 date time 日期时间格式,即${date}变量格式

    Eclipse 改动凝视的 date time 日期时间格式,即${date}变量格式 找到eclipse安装文件夹以下的plugins文件夹,搜索 org.eclipse.text ,找到一个jar ...

  8. Kafka - SQL 引擎

    Kafka - SQL 引擎分享 1.概述 大多数情况下,我们使用 Kafka 只是作为消息处理.在有些情况下,我们需要多次读取 Kafka 集群中的数据.当然,我们可以通过调用 Kafka 的 AP ...

  9. 《循序渐进Oracle》部分笔记

    1.不要用户名/密码 直接/as sysdba 是操作系统认证方式,改变安全方式 sqlnet.ora 里SQLNET.AUTHENTICATION_SERVICES=(NTS)表示启动操作系统认证; ...

  10. FZU2082

    树链剖分后要处理的是边的权值,而不是点的权值,但是只要边权下放到点,就可以了 如图 但是问题是,求图4->5路径的权值之和, 那么就会把点3给算进去 那么就要减去, 或者干脆不加进去 有两种方法 ...