Apache mahout 源码阅读笔记-DataModel之UserBaseRecommender
@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的更多相关文章
- Apache mahout 源码阅读笔记--DataModel之FileDataModel
要做推荐,用户行为数据是基础. 用户行为数据有哪些字段呢? mahout的DataModel支持,用户ID,ItemID是必须的,偏好值(用户对当前Item的评分),时间戳 这四个字段 {@code ...
- Apache mahout 源码阅读笔记--协同过滤, PearsonCorrelationSimilarity
协同过滤源码路径: ~/project/javaproject/mahout-0.9/core/src $tree main/java/org/apache/mahout/cf/taste/ -L 2 ...
- Apache Storm源码阅读笔记
欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比 ...
- Mina源码阅读笔记(四)—Mina的连接IoConnector2
接着Mina源码阅读笔记(四)-Mina的连接IoConnector1,,我们继续: AbstractIoAcceptor: 001 package org.apache.mina.core.rewr ...
- CI框架源码阅读笔记5 基准测试 BenchMark.php
上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...
- CI框架源码阅读笔记3 全局函数Common.php
从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...
- CI框架源码阅读笔记2 一切的入口 index.php
上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...
- 源码阅读笔记 - 1 MSVC2015中的std::sort
大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格 ...
随机推荐
- 基于jQuery左侧小图滚动右侧大图显示代码
今天给大家分享一款 jQuery左侧小图滚动右侧大图显示代码是一款基于jQuery实现的左侧滚动图片点击大图查看效果代码.该实例适用浏览器:IE8.360.FireFox.Chrome.Safari. ...
- 基于HTML5/CSS3可折叠的3D立方体动画
今天要给大家带来另外一款CSS3 3D立方体动画,尤其在DEMO2中可以看到,鼠标滑过立方体后,它将会被打开,从里面弹出另外一个小立方体,动画效果非常酷,非常逼真. 在线预览 源码下载 实现的代码 ...
- 16V554 的测试代码
//------------------------------------------------------------------------ #include "AT16C554 ...
- PLSQL 连接不上64位ORACLE数据库解决办法
http://it.oyksoft.com/post/6003/ huan jing bian liang TNS_ADMIN D:\OracleClient D:\OracleClient\TNS ...
- svn 脚本替换
#!/bin/bashfor i in `find /home/20180629tmp/svnfwq/uadminv4 -name .svn` do echo $i aa=`dirname $i` b ...
- SQL Server 数据库同步,订阅、发布、复制、跨服务器
随便说两句 折腾了一周,也算把数据库同步弄好了.首先局域网内搭建好,进行各种测试,弄的时候各种问题,弄好以后感觉还是挺简单的.本地测试好了,又在服务器进行测试,主要的难点就是跨网段同步,最后也解决了, ...
- TensorFlow基础笔记(2) minist分类学习
(1) 最简单的神经网络分类器 # encoding: UTF-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist i ...
- 一个区域只能放置一个组件,如果想在一个区域放置多个组件就需要使用Panel来装载
五种布局管理器: Flow Layout(流式布局):按照组件添加到容器中的顺序,顺序排放组件位置.默认为水平排列,如果越界那么会向下排列.排列的位置随着容器大小的改变而改变. Panel默认的布局管 ...
- 【BZOJ】2301: [HAOI2011]Problem b(莫比乌斯+分块)
http://www.lydsy.com/JudgeOnline/problem.php?id=2301 和这题不是差不多的嘛--[BZOJ]1101: [POI2007]Zap(莫比乌斯+分块) 唯 ...
- [ACM] FZU 2086 餐厅点餐 (枚举)
roblem Description Jack近期喜欢到学校餐厅吃饭.好吃干净还廉价. 在学校餐厅.有a种汤,b种饭.c种面条,d种荤菜,e种素菜. 为了保证膳食搭配,Jack每顿饭都会点1~2样荤菜 ...