先来看一下使用流程:
1)拿到DataModel
2)定义相似度计算模型 PearsonCorrelationSimilarity
3)定义用户邻域计算模型 NearestNUserNeighborhood
4)定义推荐模型 GenericUserBasedRecommender
5)进行推荐
  @Test
public void testHowMany() throws Exception {
DataModel dataModel = getDataModel(
new long[] {1, 2, 3, 4, 5},
new Double[][] {
{0.1, 0.2},
{0.2, 0.3, 0.3, 0.6},
{0.4, 0.4, 0.5, 0.9},
{0.1, 0.4, 0.5, 0.8, 0.9, 1.0},
{0.2, 0.3, 0.6, 0.7, 0.1, 0.2},
});
//用于计算最相似的用户,领域用户
UserSimilarity similarity = new PearsonCorrelationSimilarity(dataModel);
UserNeighborhood neighborhood = new NearestNUserNeighborhood(2, similarity, dataModel); Recommender recommender = new GenericUserBasedRecommender(dataModel, neighborhood, similarity);
List<RecommendedItem> fewRecommended = recommender.recommend(1, 2);
List<RecommendedItem> moreRecommended = recommender.recommend(1, 4);
for (int i = 0; i < fewRecommended.size(); i++) {
assertEquals(fewRecommended.get(i).getItemID(), moreRecommended.get(i).getItemID());
}
recommender.refresh(null);
for (int i = 0; i < fewRecommended.size(); i++) {
assertEquals(fewRecommended.get(i).getItemID(), moreRecommended.get(i).getItemID());
}
}

相似度计算,参考上篇的PearsonCorrelationSimilarity。

NearestNUserNeighborhood ,获取最近的N个用户,怎么实现的呢?
~/mahout-core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericUserBasedRecommender.java
  @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); //根据similarity模型进行计算,计算最相似的N个用户
long[] theNeighborhood = neighborhood.getUserNeighborhood(userID); if (theNeighborhood.length == 0) {
return Collections.emptyList();
}
//获取其他领域用户进行评分而且当前用户所没有进行评分的Item列表,作为推荐的基本池子
FastIDSet allItemIDs = getAllOtherItems(theNeighborhood, userID); //获取池子里面,当前用户偏好最高的TopN进行推荐
TopItems.Estimator<Long> estimator = new Estimator(userID, theNeighborhood); List<RecommendedItem> topItems = TopItems
.getTopItems(howMany, allItemIDs.iterator(), rescorer, estimator); log.debug("Recommendations are: {}", topItems);
return topItems;
}
Estimator的实现,是这样的:
  private final class Estimator implements TopItems.Estimator<Long> {

    private final long theUserID;
private final long[] theNeighborhood; Estimator(long theUserID, long[] theNeighborhood) {
this.theUserID = theUserID;
this.theNeighborhood = theNeighborhood;
} @Override
public double estimate(Long itemID) throws TasteException {
return doEstimatePreference(theUserID, theNeighborhood, itemID);
}
}
}
 
  protected float doEstimatePreference(long theUserID, long[] theNeighborhood, long itemID) throws TasteException {
//把相似用户对该Item的偏好累加起来,再做平均值,当做当前用户对改Item的偏好
if (theNeighborhood.length == 0) {
return Float.NaN;
}
DataModel dataModel = getDataModel();
double preference = 0.0;
double totalSimilarity = 0.0;
int count = 0;
for (long userID : theNeighborhood) {
if (userID != theUserID) {
// See GenericItemBasedRecommender.doEstimatePreference() too
Float pref = dataModel.getPreferenceValue(userID, itemID);
if (pref != null) {
double theSimilarity = similarity.userSimilarity(theUserID, userID);
if (!Double.isNaN(theSimilarity)) {
preference += theSimilarity * pref;
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)计算最相似的N个用户
2)从最相似的N个用户中,获取自己没有评分过的Item
3)预计自己对每个Item的偏好
4)取偏好最高的N个Item进行推荐

Apache mahout 源码阅读笔记-DataModel之UserBaseRecommender的更多相关文章

  1. Apache mahout 源码阅读笔记--DataModel之FileDataModel

    要做推荐,用户行为数据是基础. 用户行为数据有哪些字段呢? mahout的DataModel支持,用户ID,ItemID是必须的,偏好值(用户对当前Item的评分),时间戳 这四个字段 {@code ...

  2. Apache mahout 源码阅读笔记--协同过滤, PearsonCorrelationSimilarity

    协同过滤源码路径: ~/project/javaproject/mahout-0.9/core/src $tree main/java/org/apache/mahout/cf/taste/ -L 2 ...

  3. Apache Storm源码阅读笔记

    欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比 ...

  4. Mina源码阅读笔记(四)—Mina的连接IoConnector2

    接着Mina源码阅读笔记(四)-Mina的连接IoConnector1,,我们继续: AbstractIoAcceptor: 001 package org.apache.mina.core.rewr ...

  5. CI框架源码阅读笔记5 基准测试 BenchMark.php

    上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...

  6. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...

  7. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

  8. CI框架源码阅读笔记2 一切的入口 index.php

    上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...

  9. 源码阅读笔记 - 1 MSVC2015中的std::sort

    大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格 ...

随机推荐

  1. hdu3457(有向图的dp问题)

    同http://www.cnblogs.com/ziyi--caolu/p/3202511.html #include<iostream> #include<stdio.h> ...

  2. C语言 · Sine之舞

    基础练习 Sine之舞   时间限制:1.0s   内存限制:512.0MB    问题描述 最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功.所以他准备和奶 ...

  3. C语言 · 打印1~100间的质数(素数)

    算法提高 c++_ch02_04   时间限制:1.0s   内存限制:256.0MB      问题描述 输出1~100间的质数并显示出来.注意1不是质数. 输出格式 每行输出一个质数. 2 3 . ...

  4. Spark的操作列表

    Action 操作1. collect() ,返回值是一个数组,返回dataframe集合所有的行2. collectAsList() 返回值是一个java类型的数组,返回dataframe集合所有的 ...

  5. PHP多进程(4) :内部多进程

    说的都是只兼容unix 服务器的多进程,下面来讲讲在window 和 unix 都兼容的多进程(这里是泛指,下面的curl实际上是通过IO复用实现的). 通过扩展实现多线程的典型例子是CURL,CUR ...

  6. qtcreator 中文乱码

    qt输入法不能用,ui中不能显示中文,开发板不能显示中文,这几个一直困扰这我,网上查找资料,在代码中添加各种支持,都没有解决问题.今天刚好解决了,记录于此. 参考链接 http://blog.163. ...

  7. 【Debian】ftp安装

    http://www.2cto.com/os/201107/98311.html http://jingyan.baidu.com/article/adc815133476bdf723bf7393.h ...

  8. jhipster(springboot+datatable+jpa)后台分页,总结

    最近用datatable做了一个后台分页,但是后台实体原本没写DTO.就碰到的问题做了一下总结 一.datatable使用get方式传数据到后台,这是正常的后台分页,不涉及过滤查询和前端传递的排序字段 ...

  9. iOS 模块化

    模块化 1.公共模块 网络层 模型层(基类) 2.mvvm 3.模块化(单元模块,实现单元功能,单元测试) 4.pod 5.路由

  10. Nginx配置里的fastcgi_index和index

    在配置nginx时有时会遇到, 所以记录一下 location ^~ /wechat/ { index index.php; fastcgi_pass 127.0.0.1:9000; fastcgi_ ...