mahout推荐引擎使用hadoop(一) 生成偏好矩阵

   第一个步骤就是生成偏好矩阵,这个工作是在PreparePreferenceMatrixJob中完成的。
下面具体的分析一下这个类。

 

 if (shouldRunNextPhase(parsedArgs, currentPhase)) {
      ToolRunner.run(getConf(), new PreparePreferenceMatrixJob(), new String[]{
          "--input", getInputPath().toString(),//输入路径
          "--output", prepPath.toString(),//输出路径
          "--maxPrefsPerUser", String.valueOf(maxPrefsPerUser),
          "--minPrefsPerUser", String.valueOf(minPrefsPerUser),
          "--booleanData", String.valueOf(booleanData),//是否为boolean型的偏好数据
          "--tempDir", getTempPath().toString() });
    }

  

下边详细的分析一下PreparePreferenceMatrixJob类的实现,主要是通过三个MapReduce来完成的:

   

public class PreparePreferenceMatrixJob extends AbstractJob {

@Override
  public int run(String[] args) throws Exception {
//第一个MapReduce
Job itemIDIndex = prepareJob(getInputPath(), getOutputPath(ITEMID_INDEX), TextInputFormat.class,
            ItemIDIndexMapper.class, VarIntWritable.class, VarLongWritable.class, ItemIDIndexReducer.class,
            VarIntWritable.class, VarLongWritable.class, SequenceFileOutputFormat.class);
//第二个MapReduce
 Job toUserVectors = prepareJob(getInputPath(), getOutputPath(USER_VECTORS), TextInputFormat.class,
            ToItemPrefsMapper.class, VarLongWritable.class, booleanData ? VarLongWritable.class : EntityPrefWritable.class,
            ToUserVectorsReducer.class, VarLongWritable.class, VectorWritable.class, SequenceFileOutputFormat.class);
//第三个MapReduce
 Job toItemVectors = prepareJob(getOutputPath(USER_VECTORS), getOutputPath(RATING_MATRIX),
            ToItemVectorsMapper.class, IntWritable.class, VectorWritable.class, ToItemVectorsReducer.class,
            IntWritable.class, VectorWritable.class);
    toItemVectors.setCombinerClass(ToItemVectorsReducer.class);

}

 

 

首先说一下prepareJob()函数,他的参数列表

   (输入路径, 输出路径, Mapper类,Mapper的key,Mapper的value,reducer类,reducer的key,reducer的value)

至于这函数里边的实现就不用看了,反正就是执行了一个MapReducer操作。

 

下边挨个分析这三个MapReducer的具体计算过程:

(1) MapperItemIDIndexMapper类,将类型为Long的itemid转换成int类型的itemid_index,并输出<itemid_index, itemid>这样将所有的item先进行split

 

 

public final class ItemIDIndexMapper extends
    Mapper<LongWritable,Text, VarIntWritable, VarLongWritable>{

 @Override
  protected void map(LongWritable key,
                     Text value,
                     Context context) throws IOException, InterruptedException {
    String[] tokens = TasteHadoopUtils.splitPrefTokens(value.toString());
    long itemID = Long.parseLong(tokens[transpose ? 0 : 1]);
    //将long类型itemid转换成int类型的itemid_index
    int index = TasteHadoopUtils.idToIndex(itemID);
    //输出(itemid_index, itemid)类型
    context.write(new VarIntWritable(index), new VarLongWritable(itemID));
  }  

}

 

 

 Reducer : temIDIndexReducer类,对每一个itemid_index下的所有的itemid取最小值,并输出<itemid_index, minimumItemid>

 

public final class ItemIDIndexReducer extends
    Reducer<VarIntWritable, VarLongWritable, VarIntWritable,VarLongWritable> {
 
  //对每一个itemid_index下的所有的itemid取最小值,并输出<itemid_index, minimumItemid>
  @Override
  protected void reduce(VarIntWritable index,
                        Iterable<VarLongWritable> possibleItemIDs,
                        Context context) throws IOException, InterruptedException {
    long minimumItemID = Long.MAX_VALUE;
    for (VarLongWritable varLongWritable : possibleItemIDs) {
      long itemID = varLongWritable.get();
      if (itemID < minimumItemID) {
        minimumItemID = itemID;
      }
    }
    if (minimumItemID != Long.MAX_VALUE) {
      context.write(index, new VarLongWritable(minimumItemID));
    }
  }
  
}

 (2)Mapper :  ToItemPrefsMapper类,继承于ToEntityPrefsMapper类,作用是从文件中读取数据,并以

 

  userid,<itemid, pref>  的形式作为reducer的输出

 

public final class ToItemPrefsMapper extends ToEntityPrefsMapper {
  public ToItemPrefsMapper() {
    super(false);
  }  
}

public abstract class ToEntityPrefsMapper extends
    Mapper<LongWritable,Text, VarLongWritable,VarLongWritable> {
@Override
  public void map(LongWritable key,
                  Text value,
                  Context context) throws IOException, InterruptedException {
    String[] tokens = DELIMITER.split(value.toString());
    long userID = Long.parseLong(tokens[0]);
    long itemID = Long.parseLong(tokens[1]);
    if (itemKey ^ transpose) {
      // If using items as keys, and not transposing items and users, then users are items!
      // Or if not using items as keys (users are, as usual), but transposing items and users,
      // then users are items! Confused?
      //如果设置偏转,那么就是将userid和itemid的位置互换,也就是基于user的CF了
      long temp = userID;
      userID = itemID;
      itemID = temp;
    }
    if (booleanData) {
      context.write(new VarLongWritable(userID), new VarLongWritable(itemID));
    } else {
      float prefValue = tokens.length > 2 ? Float.parseFloat(tokens[2]) + ratingShift : 1.0f;
      //输出(userid,<itemid, pref> )类型
      context.write(new VarLongWritable(userID), new EntityPrefWritable(itemID, prefValue));
    }
  }

}

 

 Reducer : ToUserVectorsReducer类,收集同一个userid下的<itemid, pref>对,并将itemid映射成itemid_index,然后和pref组成<itemid_index, pref>对,并将同一个userid下的所有<itemid_index, pref>对保存到一个vecotr(RandomAccessSparseVector类型的)中,并输出 (userid,vector<itemid_index, pref>) 类型的结果

 

 

 

public final class ToUserVectorsReducer extends
    Reducer<VarLongWritable,VarLongWritable,VarLongWritable,VectorWritable> {

  @Override
  protected void reduce(VarLongWritable userID,
                        Iterable<VarLongWritable> itemPrefs,
                        Context context) throws IOException, InterruptedException {
    Vector userVector = new RandomAccessSparseVector(Integer.MAX_VALUE, 100);
    for (VarLongWritable itemPref : itemPrefs) {
      //将long类型的itemid映射成int类型的itemid_index
      int index = TasteHadoopUtils.idToIndex(itemPref.get());
      float value = itemPref instanceof EntityPrefWritable ? ((EntityPrefWritable) itemPref).getPrefValue() : 1.0f;
      userVector.set(index, value);
    }

    if (userVector.getNumNondefaultElements() >= minPreferences) {
      VectorWritable vw = new VectorWritable(userVector);
      vw.setWritesLaxPrecision(true);
      context.getCounter(Counters.USERS).increment(1);
      context.write(userID, vw);
    }
  }
  
}

 

(3)Mapper :ToItemVectorsMapper类,将上边(2)中的输出作为Mapper的输入,将Long类型userid映射为int类型的userid_index,并输出( itemid_index, <userid_index, pref> )类型

 

public class ToItemVectorsMapper
    extends Mapper<VarLongWritable,VectorWritable,IntWritable,VectorWritable> {

  @Override
  protected void map(VarLongWritable rowIndex, VectorWritable vectorWritable, Context ctx)
      throws IOException, InterruptedException {
    Vector userRatings = vectorWritable.get();

    int numElementsBeforeSampling = userRatings.getNumNondefaultElements();
    userRatings = Vectors.maybeSample(userRatings, sampleSize);
    int numElementsAfterSampling = userRatings.getNumNondefaultElements();

    int column = TasteHadoopUtils.idToIndex(rowIndex.get());
    VectorWritable itemVector = new VectorWritable(new RandomAccessSparseVector(Integer.MAX_VALUE, 1));
    itemVector.setWritesLaxPrecision(true);

    Iterator<Vector.Element> iterator = userRatings.iterateNonZero();
    while (iterator.hasNext()) {
      Vector.Element elem = iterator.next();
      //这里vector.setQuick()是将键值对插入到一个map里,因为column不变,所以每次替换value
      itemVector.get().setQuick(column, elem.get());
      //输出( itemid_index, <userid_index, pref> )
      ctx.write(new IntWritable(elem.index()), itemVector);
    }

    ctx.getCounter(Elements.USER_RATINGS_USED).increment(numElementsAfterSampling);
    ctx.getCounter(Elements.USER_RATINGS_NEGLECTED).increment(numElementsBeforeSampling - numElementsAfterSampling);
  }

}

 

 Reducer :ToItemVectorsReducer类,将同一个itemid_index下的<userid_index, pref>对收集到一起,保存在一个vector中,并输出 ( itemid_index,vector<userid_index, pref> ) 类型

 

public class ToItemVectorsReducer extends Reducer<IntWritable,VectorWritable,IntWritable,VectorWritable> {

  @Override
  protected void reduce(IntWritable row, Iterable<VectorWritable> vectors, Context ctx)
      throws IOException, InterruptedException {
    //合并同一个itemid_index下的<userid_index, pref>对
    VectorWritable vectorWritable = VectorWritable.merge(vectors.iterator());
    vectorWritable.setWritesLaxPrecision(true);
    ctx.write(row, vectorWritable);
  }
}

  

 至此,在PreparePreferenceMatrixJob中的所有MapReduce计算都完成了,最终我们看到,生成的是一个

itemid_index,  vector<userid_index, pref>   的偏好矩阵

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

大数据() - Mahout 传统数据挖掘/机器学习库存在的问题         缺少个活跃的技术社区         扩展性差         文档化差,缺少实例         不开源,商业化库         通常由研究机构开发         实施性差 Apache Mahout优点         技术社区活跃         扩展性好         文档化好,实例丰富 阅读详情

相关推荐

Hadoop推荐系统:构建个性化推荐引擎

本文旨在为读者提供个全面的指南,介绍如何使用Hadoop生态系统构建高效、可扩展的个性化推荐系统。推荐系统的基本原理和算法Hadoop推荐系统中的核心作用实际实现方案和优化技巧性能评估和调优方法本文首先介绍推荐系统和Hadoop的基本概念,然后深入探讨核心算法及其Hadoop实现,接着通过实际案例展示完整实现流程,最后讨论应用场景和未来趋势。Hadoop个开源的分布式计算框架,用于存储和处理大规模数据集推荐系统:种信息过滤系统,预测用户对物品的评分或偏好协同过滤。

架构师的AI之路,分享AI应用开发架构的学习与实践。 253

推荐系统学习笔记

漫谈“推荐系统”  http://youngfor.me/post/recsys/man-tan-tui-jian-xi-tong   下面的大部分文字内容转自@复旦李斌的博客,非常白话的review了推荐系统领域的些研究内容以及存在的挑战,其中穿插了些自己理解笔记,以及添加了些互联网上其他相关资料(如,七月在线)。 1.背景:   先谈谈问题背景,故事是这样的:互联网出现后,随着网上...

Farmer-Lei 4026

推荐系统7:推荐算法实战:mahout推荐算法框架

1.Mahout介绍 1.1概述 根据百度的解说,Mahout 是 Apache Software Foundation(ASF) 旗下的个开源项目,提供些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。Mahout包含许多实现,包括聚类、分类、推荐过滤、频繁子项挖掘。此外,通过使用 Apache Hadoop 库,Mahout 可以有效地扩展到云中。 1....

qq_28286027的博客 684

推荐系统三十六式:矩阵分解 总结

作者:jliang https://blog.csdn.net/jliang3 1.重点归纳 1)评分预测问题只是很典型,其实并不大众,毕竟在实际的应用中,评分数据很难收集到;与之相对的另类问题是行为预测才是平民级推荐问题。在真正的推荐系统的实际应用中,评分预测实际上场景很少,而且数据很少,相比预测评分,预测“用户会对物品干出什么事”会更加有效。 2)矩阵分解 (1)矩阵...

jliang3的博客 2655

Hadoopmahout推荐hadoop偏好矩阵-PreparePreferenceMatrixJob

mahout推荐包括两部分,部分是单机版的推荐,主要是以org.apache.mahout.cf.taste.*包下面;另种则是hadoop版本的推荐主要是以org.apache.mahout.cf.taste.hadoop.*包下面。下面我们针对hadoop版本进行分析。在org.apache.mahout.cf.taste.hadoop.item包下面的RecommenderJob开始。

zwan0518的专栏 2139

基于用户行为分析建立用户偏好模型

基于用户行为分析建立用户偏好模型 2013-09-08 18:23  2736 http://zisong.me/post/ji-zhu/ji-yu-yong-hu-xing-wei-fen-xi-jian-li-yong-hu-pian-hao-mo-xing 我们经常将个性化推荐的思想简单地抽象为:通过用户的行为推测出用户的兴趣,从而给用户推荐满足他们兴趣的物品。那我

crackly的专栏 9636

推荐系统中的矩阵分解总结

最近学习矩阵分解,但是学了好多种类,都乱了,看了这篇文章,系统性的总结了矩阵分解,感觉很棒,故分享如下: 前言 推荐系统中最为主流与经典的技术之是协同过滤技术(Collaborative Filtering),它是基于这样的假设:用户如果在过去对某些项目产生过兴趣,那么将来他很可能依然对其保持热忱。其中协同过滤技术又可根据是否采用了机器学习思想建模的不同划分为基于内存的协同过滤(Memory...

Rnan_prince的博客 4万+

Apache Mahout的Taste基于Hadoop实现协同过滤推荐引擎的代码分析

Taste 是 Apache Mahout 提供的个协同过滤算法的高效实现,它是个基于Java实现的可扩展的高效的推荐引擎。 该推荐引擎是用这样简单的数据格式表达用户对物品的偏好。 以此为输入数据,计算后就可以得到为每个user推荐的items列表。 他提供了方便的单机版的编程接口,也提供了基于hadoop的分布式的实现。 单机版的编程接口主要适用于写demo和做算法的评估,若处理

zhang434的专栏 1162

基于hadoop推荐算法-mahout

http://blackproof.iteye.com/blog/2110877 基于hadoop推荐算法,讲其中mahout实现的基于项目的推荐算法 分为4步: 1.获得人-物 用户矩阵     输入为所有人对物品的评价或关联     map端输出key为人,value为物品+倾好度     reeduce端输出key为人,vallue为多个物品+倾好度

onlyForCloud的专栏 3858

mahout 推荐算法 java_推荐系统之推荐算法实战:mahout推荐算法框架

1.Mahout介绍1.1概述根据百度的解说,Mahout 是 Apache Software Foundation(ASF) 旗下的个开源项目,提供些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。Mahout包含许多实现,包括聚类、分类、推荐过滤、频繁子项挖掘。此外,通过使用 Apache Hadoop 库,Mahout 可以有效地扩展到云中。1.2发展...

weixin_35286137的博客 2008

初识协同过滤算法,以及hadoopMahout实现

1.推荐系统简介 推荐系统广泛存在于各类网站中,作为个应用为用户提供个性化的推荐。它需要用户的历史数据,般由三个部分组成:基础数据、推荐算法系统、前台展示。基础数据包括很多维度,包括用户的访问、浏览、下单、收藏,用户的历史订单信息,评价信息等很多信息;推荐算法系统主要是根据不同的推荐诉求由多个算法组成的推荐模型;前台展示主要是对客户端系统进行响应,返回相关的推荐信息以供展示。 基础数据主...

流的博客 1080

mahout基于hadoop推荐引擎代码分析

mahout的taste框架是协同过滤算法的实现。它支持DataModel,如文件、数据库、NoSQL存储等,也支持hadoop的MapReduce。这里主要分析的基于MR的实现。 基于MR的CF实现主要流程就在org.apache.mahout.cf.taste.hadoop.item.RecommenderJob类中(注意mahout有两个RecommendJob,要看清楚是

lhfredfly的专栏 1196

mahout推荐引擎使用hadoop

        Taste 是 Apache Mahout 提供的个协同过滤算法的高效实现,它是个基于Java实现的可扩展的高效的推荐引擎。扩展性是指使用hadoop进行mapreduce计算,提高运算性能。         最近开始看源码,分析下,做个笔记。 ItemSimilarityJob类是mahout使用hadoop推荐引擎的主要实现类,下面开始分析。 run()函数是启动...

eric的学习笔记 173

大数据技术与推荐系统(7)Mahout推荐算法实战

文章目录Mahout概述Mahout推荐算法介绍Mahout推荐算法实战 Mahout概述 基于Spark/Flink/H2O开发的数据挖掘/机器学习库 截止2014年底,mahout不再接收任何MapReduce开发的算法,转向spark 良好的扩展性和容错性 充分利用了MapReduce/Spark/Flink 和HDFS 的扩展性和容错性 属于Hadoop生态系统重要组成部分 ...

个人记录使用 1234

机器学习 hadoop-Mahout

协同过滤 测试数据 用户ID,物品ID,评分 1,101,5.0 1,102,3.0 1,103,2.5 2,101,2.0 2,102,2.5 2,103,5.0 2,104,2.0 3,101,2.5 3,104,4.0 3,105,4.5 3,107,5.0 4,101,5.0 4,103,3.0 4,104,4.5 4,106,4.0 5,101,4.0 5,102,3.0 5,10...

LJ2415的博客 388

(转)mahout推荐引擎使用hadoop

Taste 是 Apache Mahout 提供的个协同过滤算法的高效实现,它是个基于Java实现的可扩展的高效的推荐引擎。扩展性是指使用hadoop进行mapreduce计算,提高运算性能。 最近开始看源码,分析下,做个笔记。 ItemSimilarityJob类是mahout使用hadoop推荐引擎的主要实现类,下面开始分析。 run()函数是启动函数: ...

weixin_30670151的博客 87
上一篇: mahout实现的自然语言算法
下一篇: mahout推荐引擎使用hadoop
eric509
博客等级 码龄19年 8粉丝 170原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值