Taste 是 Apache Mahout 提供的一个协同过滤算法的高效实现,它是一个基于Java实现的可扩展的高效的推荐引擎。
该推荐引擎是用<userid,itemid,preference>这样简单的数据格式表达用户对物品的偏好。
以此为输入数据,计算后就可以得到为每个user推荐的items列表。
他提供了方便的单机版的编程接口,也提供了基于hadoop的分布式的实现。
单机版的编程接口主要适用于写demo和做算法的评估,若处理大规模数据,还是需分布式的实现。
以下是对org.apache.mahout.cf.taste.hadoop.item.RecommenderJob的各MapReduce步骤的一个解读。
Taste 实现一个分布式的协同过滤推荐共经历了如下12个MapReduce步骤。
以下分析了各步骤的Mapper和Reducer都做了哪些工作,并有什么格式的数据输出。
代码分析:
1、计算item的itemid_index和最小itemid值
1.1、ItemIDIndexMapper.class, VarIntWritable.class, VarLongWritable.class,
用原始输入,将userid,itemid,pref数据转成itemid_index,itemid
1.2、ItemIDIndexReducer.class, VarIntWritable.class, VarLongWritable.class,
在itemid_index,Iterator<itemid>中找最小的itemid,输出itemid_index,minimum_itemid
此处只是保存一个int型的itemid_index索引和对应的long型的itemid的映射
2、计算各user的item偏好向量,即Vector<item,pref>
2.1、ToItemPrefsMapper.class, VarLongWritable.class, booleanData ? VarLongWritable.class : EntityPrefWritable.class,
用原始输入,读入偏好数据,得到userid,<itemid,pref>
2.2、ToUserVectorReducer.class, VarLongWritable.class, VectorWritable.class,
将userid,Iterator<itemid,pref>中的itemid变成itemid_index,得到userid,Vector<itemid_index,pref>,后者用RandomAccessSparseVector来存。
3、统计数据中有多少个user
3.1、CountUsersMapper.class,CountUsersKeyWritable.class,VarLongWritable.class,
用步骤2的输出,统计独立userid数目,先转换数据为userid,userid
3.2、CountUsersReducer.class,VarIntWritable.class,NullWritable.class,
通过CountUsersPartitioner将所有数据发到一个区,一个Reducer来处理
由于userid都已排序,所以可以用极简单的方式来统计出独立userid数
输出只有一个值,即用户数
4、计算item的user偏好向量,即Vector<userid,pref>,也即拿步骤2的结果做矩阵的修剪和转置
4.1、MaybePruneRowsMapper.class,IntWritable.class,DistributedRowMatrix.MatrixEntryWritable.class,
用步骤2的输出,按指定的maxCooccurrences参数值来修剪Vector的数目,目的是控制计算的规模,减少计算量
然后转为以userid_index为列号、itemid_index为行号、pref为值的矩阵,用MatrixEntryWritable表示矩阵。
输出为itemid_index,Matrix<userid_index,itemid_index,pref>
4.2、ToItemVectorsReducer.class,IntWritable.class,VectorWritable.class,
输出为itemid_index,Vector<userid_index,pref>,相当于对步骤2的结果进行了矩阵的转置,
有了偏好矩阵数据,接下来会调用RowSimilarityJob来计算行的相似度
此处的行是item,所以默认是item-base的CF。
但其实可以通过传入是否转置的参数来对步骤1进行调整,将userid和itemid转换,就可以实现user-base的CF。
此处也可以通过similarityClassname参数来指定用哪种算法来计算相似度。
RowSimilarityJob将通过接下来的3个步骤来实现:
5、用相似度算法给向量赋权
5.1、RowWeightMapper.class,VarIntWritable.class,WeightedOccurrence.class,
用相应的相似度算法来计算步骤4的输出,计算每个itemid_index所对应的Vector<userid_index,pref>的weight。
输出为userid_index,WeightedOccurrence<itemid_index,pref,weight>,WeightedOccurrence是一个简单的数据封装类。
5.2、WeightedOccurrencesPerColumnReducer.class,VarIntWritable.class,WeightedOccurrenceArray.class,
将Iterator<WeightedOccurrence>简单变为WeightedOccurrenceArray,后者只是简单继承了ArrayWritable。
最后输出结果为userid_index,WeightedOccurrenceArray,数组的数据项是WeightedOccurrence<itemid_index,pref,weight>
6、用相似度算法计算相似度,得到相似度矩阵
6.1、CooccurrencesMapper.class,WeightedRowPair.class,Cooccurrence.class,
取出步骤5的结果,将WeightedOccurrenceArray的数据双重循环,拼装如下的KV数据结构
WeightedRowPair<itemid_indexA,itemid_indexB,weightA,weightB>,Cooccurrence<userid_index,prefA,prefB>
6.2、SimilarityReducer.class,SimilarityMatrixEntryKey.class,DistributedRowMatrix.MatrixEntryWritable.class,
此步骤的Map输出,也即Reduce的输入是WeightedRowPair<itemid_indexA,itemid_indexB,weightA,weightB>, Iterator<Cooccurrence<userid_index,prefA,prefB>>
也即itemA和itemB的weight,以及不同user对itemA和itemB的pref。
相应的Similarity实例就可以利用以上数据计算itemA与itemB的相似度评分similarityValue
输出结果为SimilarityMatrixEntryKey<itemid_indexA,similarityValue>,Matrix<itemid_indexA,itemid_indexB,similarityValue>
也就是不同item和itemA的俩俩相似度,得到一个相似度矩阵
7、将相似度矩阵转为向量存储
7.1、Mapper.class,SimilarityMatrixEntryKey.class,DistributedRowMatrix.MatrixEntryWritable.class,
将步骤6的结果简单读入,item相似度矩阵
7.2、EntriesToVectorsReducer.class,IntWritable.class,VectorWritable.class,
输出为itemid_indexA,Vector<itemid_indexX,similarityValue>,Vector用SequentialAccessSparseVector存储。
也就是输出为不同的其他item与itemA之间的相似度值
8、PartialMultiply的预处理1,填充vector部分的数据
8.1、SimilarityMatrixRowWrapperMapper.class, VarIntWritable.class, VectorOrPrefWritable.class,
用步骤7的相似度数据,输出itemid_index,VectorOrPrefWritable(vector,null,null)
8.2、Reducer.class, VarIntWritable.class, VectorOrPrefWritable.class,
默认Reducer,直接输出Mapper的输出
9、PartialMultiply的预处理2,填充userid和pref部分的数据
9.1、UserVectorSplitterMapper.class, VarIntWritable.class, VectorOrPrefWritable.class,
如果提供了一个userid列表文件,Mapper初始化时会先读入该文件到FastIDSet<userid>中
如果userid不在这个Set中,则会直接return,也就是只会为该列表中的user做推荐
用步骤2的用户对各item的偏好数据,输出itemid_index,VectorOrPrefWritable(null,userid,pref)
9.2、Reducer.class, VarIntWritable.class, VectorOrPrefWritable.class,
默认Reducer,直接输出Mapper的输出
10、拼装两个PartialMultiply预处理的数据
10.1、Mapper.class, VarIntWritable.class, VectorOrPrefWritable.class,
用FileInputFormat.setInputPaths指定多个路径,将步骤8和9的输出同时作为输入
10.2、ToVectorAndPrefReducer.class, VarIntWritable.class, VectorAndPrefsWritable.class,
将VectorOrPrefWritable(vector,null,null)和VectorOrPrefWritable(null,userid,pref)
变为VectorAndPrefsWritable(vector,List<userid>,List<pref>)
最后的输出是itemid_index,VectorAndPrefsWritable(vector,List<userid>,List<pref>)
11、如果设置了item过滤文件则读取,作为黑名单
11.1、ItemFilterMapper.class, VarLongWritable.class, VarLongWritable.class,
简单读入item过滤文件,输出为itemid,userid,这相当于“黑”名单,用于后面推荐结果的过滤。
11.2、ItemFilterAsVectorAndPrefsReducer.class, VarIntWritable.class, VectorAndPrefsWritable.class,
输出为itemid_index,VectorAndPrefsWritable(vector,List<userid>,List<pref>)
其中vector的值为vector(itemid_index,Double.NaN),pref的值都用1.0f来填充。
注意,vector的第二项数据,也即similarityValue被设置为Double.NaN,后面将会用这个来判断这是否是黑名单。
12、用相似度矩阵的PartialMultiply做推荐计算
12.1、PartialMultiplyMapper.class, VarLongWritable.class, PrefAndSimilarityColumnWritable.class,
如果步骤11存在,则用FileInputFormat.setInputPaths指定多个路径,将步骤10和11的输出同时作为输入
也即输入为itemid_index,VectorAndPrefsWritable(vector,List<userid>,List<pref>),其中vector的值为Vector<itemid_index,similarityValue>
输出为userid,PrefAndSimilarityColumnWritable(pref,vector<itemid_index,similarityValue>)
12.2、AggregateAndRecommendReducer.class, VarLongWritable.class, RecommendedItemsWritable.class,
初始化时,会读入步骤1的结果,是一个HashMap<itemid_index,itemid>,也即index和itemid的映射
若设置了item白名单文件,则初始化时也会读入文件到FastIDSet<itemid>,推荐结果必须在这里边。和步骤11的黑名单相反。
Reducer在处理时会区分是否是booleanData而用不同的处理逻辑,此处我们主要讨论非booleanData,也即有实际pref数据的情况而不是默认用1.0f来填充的pref。
Reducer中进行PartialMultiply,按乘积得到的推荐度的大小取出最大的几个item。
处理的过程中需要将itemid_index通过HashMap转换回itemid,并且用“黑”“白”名单进行过滤。
白名单很容易理解,用集合是否为空和集合的contains();
黑名单是判断Float.isNaN(similarityValue),因为此前在步骤11的输出时黑名单的similarityValue被设置为了Double.NaN。
对于非booleanData,是用pref和相似度矩阵的PartialMultiply得到推荐度的值来进行排序。
而booleanData的pref值都是1.0f,所以去计算矩阵相乘的过程没有意义,直接累加相似度的值即可。
用这个数据排序就可得到推荐结果。
输出为userid,RecommendedItemsWritable,后者实际是List<RecommendedItem<itemid,pref>>,
这里的pref是相似度矩阵的PartialMultiply或是相似度累加计算出来的值而非实际值。
后注:
以上提到的FastIDSet,SequentialAccessSparseVector,RandomAccessSparseVector等等数据结构,
是Mahout提供的一些大数据量存储和处理的一些高效实现,
针对数据的特点而做的有针对性的优化,同时解决性能和空间的问题。
在Mahout in Action的讨论CF和Cluster等的“数据的表达”章节中有专门的阐述,此处不再详细解释。
相关推荐
基于Mahout实现协同过滤推荐算法的电影推荐系统
基于Apache Mahout框架实现的具有协同过滤功能的推荐系统源码+数据+项目操作说明.zip 该项目是使用Apache Mahout框架创建的具有协同过滤功能的推荐系统。该系统使用一个音乐推荐数据集作为研究目的的输入,但可以...
MovieRecommender基于Mahout实现协同过滤推荐算法的电影推荐系统^
基于Java+Mahout的协同过滤推荐算法图书推荐系统源码+项目说明.zip 基于协同过滤的书籍推荐系统,图书推荐系统 最新版本,在原先手动计算皮尔逊相似度和评分矩阵的基础上添加了Mahout实现的协同过滤推荐算法。 ...
基于Mahout协同过滤实现图书推荐系统_书籍推荐系统源码+项目说明.zip 基于协同过滤的书籍推荐系统,图书推荐系统 最新版本,在原先手动计算皮尔逊相似度和评分矩阵的基础上添加了Mahout实现的协同过滤推荐算法. ...
基于协同过滤算法的电影推荐系统.docx基于协同过滤算法的电影推荐系统.docx基于协同过滤算法的电影推荐系统.docx基于协同过滤算法的电影推荐系统.docx基于协同过滤算法的电影推荐系统.docx基于协同过滤算法的电影...
#资源达人分享计划#
本系统在ANT下可以直接运行,...电影推荐系统中引用了Apache Mahout提供的一个协同过滤算法的推荐引擎Taste,它实现了最基本的基于用户和基于内容的推荐算法,并提供了扩展接口,使用户方便的定义和实现自己的推荐算法。
该资源是在Eclipse平台里,使用Mahout库的API,实现基于用户的协同过滤算法,从而进行商品推荐。 软件环境是:win7 64位 +Eclipse4.4 + jdk1.6, 用到了7个.jar包, 分别为:commons-logging-1.2.jar, commons-...
推荐引擎利用特殊的信息过滤(IF,Information Filtering)技术,将不同的内容(例如电影、音乐、书籍、新闻、图片、网页等)推荐给可能感兴趣的用户。通常情况下,推荐引擎的实现是通过将用户的个人喜好与特定的...
MovieRecommender是一个基于Apache Mahout协同过滤算法实现的电影推荐系统。该系统主要由Java语言编写,同时整合了JavaScript以提供丰富的用户交互体验。整个项目包含62个文件,涵盖了多种类型,旨在为用户提供一个...
教你成功运行mahout的taste webapp例子,网上的很多资料说的不清楚,或者版本冲突。正确的版本是jdk1.6 maven3.0.5 mahout0.5 。 摸索良久,亲测有效!
具体步骤,参见博客:http://blog.csdn.net/fufengrui/article/details/17022535
在Spring Boot中,可以使用各种工具和库来实现上述步骤,例如使用Spring Data JPA来处理数据存储和查询,使用Apache Mahout或者LibRec来实现协同过滤算法,使用Thymeleaf或者Vue.js来实现推荐列表的展示。
#资源达人分享计划#
基于mahout的协同过滤,个性化推荐算法实现。源码是java,可单机运行
项目简述:MovieRecommender-1是一个基于Apache Mahout库实现的协同过滤推荐系统。该系统利用Java语言开发,旨在为用户提供个性化的电影推荐服务。通过分析用户行为和数据,MovieRecommender-1能够智能地推荐符合...
This book is a practical guide that explains the classification algorithms provided in Apache Mahout with the help of actual examples. Starting with the introduction of classification and model ...