来自:http://www.codesky.net/article/201206/171862.html

mahout的taste框架是协同过滤算法的实现。它支持DataModel,如文件、数据库、NoSQL存储等,也支持Hadoop的MapReduce。这里主要分析的基于MR的实现。

基于MR的CF实现主要流程就在 org.apache.mahout.cf.taste.Hadoop.item.RecommenderJob类中(注意mahout有两个 RecommendJob,要看清楚是哪一个包)。这 个类的run方法就包含了所有的步骤。从上到下,完整的其实有10步(中间计算item相似度其实拆分成了3个job,我们也当做是一个phase吧), 也就是说,如果指定了所有的必要参数,运行一次item-based CF算法,会执行12个JOB,当然有的步骤是可以忽略的,下面会讲。以下就是详细的每一步骤的分析:

phase1: itemIDIndex

这步主要是将itemId转成一个int。这里设计上其实有点小问题,如果item的数量非常多,比如超过int的最大值,那就有可能会出现重合了。所以用long其实更为合适。

input:用户评分文件(这也是我们最原始的输入了),格式一般为:userId t itemId t score。注意输入必须是textfile的。可能是为了方便测试吧,mahout的很多包默认输出都是textfile格式的。

map:(index, itemId)

reduce: (index, itemId)

phase2: toUserVector

input:用户评分文件

param: --userBooleanData如果这个参数为true,则会忽略评分列,对于买或不买这类数据有时需要指这定这个值。

map: (userId, itemId,pref)

reduce: 以用户为key,输出成向量形式è (userId, VectorWritable<itemId, pref>)

phase3: countUser,计算用户数

map: (userId)

reduce: 输出总用户数count

phase4: maybePruneAndTranspose

input: phase2的输出:userVector

param: --maxCooccurrences

map: (userId,Vector<itemId, pref>) è(itemId,DistributedRowMatrix<userId,pref>),注意如果指定了—maxCooccurrences参数,这里会有裁剪,www.codesky.net 每个userId最多对maxCooccurrences的itemId打分

这里的DistributedRowMatrix,分布式行矩阵:行:itemId, 列:userId

reduce: (itemId, VectorWritable<userId,pref>)

phase5: RowSimilarityJob

这一步比较关键,计算item相似度,它拆分成了三个JOB。

param: --numberOfColumns, --similarityClassname,--maxSimilaritiesPerRow(默认:100)

job1:weight

input:phase4的输出

map: (itemId, VectorWritable <userId, pref>) ==>(userId, WeightedOccurrence<itemId, pref, weight>)

这里的weight,对于欧氏向量距离,或者Pearson距离等,均为Double.NaN,即无效。在LoglikelihoodVectorSimilarity中有用到weight的值。

reduce:(userId, WeightedOccurrenceArray<itemId, pref, weight>)

job2:pairwise similarity *item相似度计算*

map: 对同一用户的所有item-rating,输出两两item之间的关系 ==>(WeightedRowPair<itemA, itemB, weightA, weightB>, coocurrence<userId,valueA, valueB>) (同上,这里的权重weightA,B对于欧氏距离等可以忽略)

reduce: 在这端,以<itemA,itemB>为key聚合了来自不同map的所有用户的 打分,最后输出itemA和B的对称相似度(即以itemA为key或以itemB为key)==> (SimilarityMatrixEntryKey<itemA,similarity>, MatrixEntryWritable<WeightedRowPair<itemA, itemB,weightA, weightB>>) , (SimilarityMatrixEntryKey<itemB,similarity>, MatrixEntryWritable<WeightedRowPair<itemB, itemA,weightB, weightA>>)

job3:entries2vectors *汇总item的相似items*

      param: --maxSimilaritiesPerRow

map: (itemA, itemB, similarity) & (itemB,itemA, similarity) 这里在group的时候按相似度降序做了排序,如果有--maxSimilaritiesPerRow参数,则会做裁剪。

reduce: (itemA, VectorWritable <item,similarity>)

至此,item相似度计算完毕。

phase6: prePartialMultiply1 

input: phase5的最后输出(即item相似度)

map: 直接输出item对应的相似items,这里用VectorOrPrefWritable做了封装,表明有可能是相似度向量,也有可能是对item的打分,并且对item为自己的,将相似度设为Double.NaN,以过滤自身。è(itemId,VectorOrPrefWritable<item, similarity>)

reduce: IdentityReducer

phase7: prePartialMultiply2

input: phase2的输出userVectors

map: 输出:(itemId, VectorOrPrefWritable<userId, pref>)

这里默认考虑用户对10个item的评分,可以通过maxPrefsPerUserConsidered参数调整。

如果指定了usersFile,则在setup时会把所有的userId读入内存,用于过滤。如果map输入数据的userID不在usersFile中,则会被忽略。注意,这是mahout的设计bug,对于比较大的数据集,很有可能造成OOM(事实上在我的测试程序中已经出现OOM了…),这种bug下面还会出现。输出的是用户的评分,同phase6的VectorOrPrefWritable的封装。

reduce: IdentityReducer

phase8: partialMultiply

input: 6和7的输出:prePartialMultiply1, prePartialMultiply2

map: Identity。由于6和7的输出的key均为itemId,因而在reduce端同一item的相似item以及对应的用户评分会聚合到一起。

reduce:(itemId, VectorAndPrefsWritable<similarityMatrix, List<userId>,List<pref>>) 没做特殊处理,直接合在一起,输出相似度矩阵,所有的userId及对item的打分。

phase9: itemFiltering 

将过滤文件输出成<userId, itemId>。如果指定了--filterFile参数,则在最后的聚合推荐中会过滤userId对应的items。这一步在实际中多数是可以忽略的,只要不指定这个参数即可。

phase10: aggregateAndRecommend

map: 对每个用户,输出对当前item的评分,以及与当前item的所有相似 itemsè(userId, PrefAndSimilarityColumnWritable<pref,vector<item, similarity>>)

reduce: 聚合了这个用户所有的评分历史,以及相似items,计算对该用户的推荐结果 è (userId, List<itemId>)。

注意在reduce的setup中,会将phase1产生的所有itemId到index的映射读入内存,这里只要Item数据集稍大,就会OOM。这是比较严重的设计bug。

事实上,如果item是正规的整数,而不是guid之类的,phase1和这一步的读入内存是完全可以略掉的。这样的话 就完全可以在企业级的数据集上使用(我的测试数据集是15亿+的user-item-rating,1.5亿+的用户,在最后这一步挂掉了,前面所有 phase都能跑成功)。

至此,已经形成了推荐结果,CF完成。

以上的所有步骤中,phase5的计算item相似度是最慢的(这个其实也很直觉)。

mahout基于Hadoop的CF代码分析(转)的更多相关文章

  1. 【Machine Learning】Mahout基于协同过滤(CF)的用户推荐

    一.Mahout推荐算法简介 Mahout算法框架自带的推荐器有下面这些: l  GenericUserBasedRecommender:基于用户的推荐器,用户数量少时速度快: l  GenericI ...

  2. Hive -- 基于Hadoop的数据仓库分析工具

    Hive是一个基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库 ...

  3. 【转】阿里巴巴技术专家杨晓明:基于Hadoop技术进行地理空间分析

    转自:http://www.csdn.net/article/2015-01-23/2823687-geographic-space-base-Hadoop [编者按]交通领域正产生着海量的车辆位置点 ...

  4. 基于hadoop分析,了解hive的使用

    一.Hadoop理论 Hadoop是一个专为离线和大规模数据分析而设计的,并不适合那种对几个记录随机读写的在线事务处理模式. Hadoop=HDFS(文件系统,数据存储技术相关)+ Mapreduce ...

  5. 开源项目kcws代码分析--基于深度学习的分词技术

    http://blog.csdn.net/pirage/article/details/53424544 分词原理 本小节内容参考待字闺中的两篇博文: 97.5%准确率的深度学习中文分词(字嵌入+Bi ...

  6. Hadoop基础-HDFS数据清理过程之校验过程代码分析

    Hadoop基础-HDFS数据清理过程之校验过程代码分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想称为一名高级大数据开发工程师,不但需要了解hadoop内部的运行机制,还需 ...

  7. mahout demo——本质上是基于Hadoop的分步式算法实现,比如多节点的数据合并,数据排序,网路通信的效率,节点宕机重算,数据分步式存储

    摘自:http://blog.fens.me/mahout-recommendation-api/ 测试程序:RecommenderTest.java 测试数据集:item.csv 1,101,5.0 ...

  8. (转)基于FFPMEG2.0版本的ffplay代码分析

    ref:http://zzhhui.blog.sohu.com/304810230.html 背景说明 FFmpeg是一个开源,免费,跨平台的视频和音频流方案,它提供了一套完整的录制.转换以及流化音视 ...

  9. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

随机推荐

  1. Windows:C:\Windows\System32\drivers\etc\hosts

    原文地址:http://zhumeng8337797.blog.163.com/blog/static/100768914201001983953188/. host是一个没有扩展名的系统文件,可以用 ...

  2. 高效的找出两个List中的不同元素

    /* * TestList.java * Version 1.0.0 * Created on 2017年12月15日 * Copyright ReYo.Cn */ package reyo.sdk. ...

  3. 新闻编辑室第三季/全集The Newsroom迅雷下载

    第三季 The Newsroom Season 3 (2014)看点:今日他们终于公布了续订第三季的消息,但同时也宣称第三季将会是<新闻编辑室>的最终季,对剧迷们来说可谓苦乐参半.讲述了一 ...

  4. SQLUnit 环境搭建

    1 技术须要积累 前几天去一位笛友小赖家玩,才知道他的笛子吹得好不是偶然.是由于他真的用功了,电脑里面下载有超多的视频.教程等!这真的非常让我震撼!一直是在公司做技术,但资料考不出来,而我整理了多少技 ...

  5. [Web 前端] React高级教程(es6)——(2)对于Refs最新变动的理解

    cp : https://blog.csdn.net/liwusen/article/details/53384561 1.什么是ReactJS中的refs 在React中组件并不是真实的 DOM 节 ...

  6. [转] OpenStack IPSec VPNaaS

    OpenStack IPSec VPNaaS ( by quqi99 ) 作者:张华  发表于:2013-08-03版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声 ...

  7. 可重入读写锁ReentrantReadWriteLock基本原理分析

    前言 本篇适用于了解ReentrantLock或ReentrantReadWriteLock的使用,但想要进一步了解原理的读者.见于之前的分析都是借鉴大量的JDK源码,这次以流程图的形式代替源码,希望 ...

  8. [转]PHP SOCKET编程

    FROM : http://blog.csdn.net/hguisu/article/details/7448528 1. 预备知识 一直以来很少看到有多少人使用php的socket模块来做一些事情, ...

  9. Django创建自定义错误页面400/403/404/500等

    直接参考: https://zhuanlan.zhihu.com/p/38006919 DEBUG =True的话,为开发环境,显示不了404页面.

  10. System.Reflection.TargetException:“非静态方法需要一个目标。”

    报错:TargetException, 非静态方法需要一个目标,非静态方法 如果实例为null,调用实例方法会报如上错. 解决办法: 检查实例是否为null,考虑什么情况下实例为null,然后排除实例 ...