mahout之推荐系统源码笔记(3) ---执行推荐之RecommenderJob

本文详细介绍了Mahout推荐系统中RecommenderJob的执行过程,包括如何通过RowSimilarityJob获取物品相似度矩阵,并使用RecommenderJob进行推荐。文中讲解了SimilarityMatrixRowWrapperMapper和UserVectorSplitterMapper的作用,以及如何通过ToVectorAndPrefReducer进行数据融合和推荐。最后,通过实例展示了推荐算法的工作原理,解释了如何避免推荐已评分的项目。
摘要由CSDN通过智能技术生成

mahout之推荐系统源码笔记(3) —执行推荐之RecommenderJob

本笔记承接笔记二。

在笔记2中我们通过RowSimilarityJob获取了所有物品之间的相似度矩阵,通过这个矩阵,接下来我们就可以开始推荐了~

首先我们回到RecommenderJob。RecommenderJob在执行RowSimilarityJob之后执行了下面这个job:

    Job partialMultiply = new Job(getConf(), "partialMultiply");
    Configuration partialMultiplyConf = partialMultiply.getConfiguration();
    //两个map
    MultipleInputs.addInputPath(partialMultiply, similarityMatrixPath, SequenceFileInputFormat.class,
            SimilarityMatrixRowWrapperMapper.class);
    MultipleInputs.addInputPath(partialMultiply, new Path(prepPath, PreparePreferenceMatrixJob.USER_VECTORS),
            SequenceFileInputFormat.class, UserVectorSplitterMapper.class);
    partialMultiply.setJarByClass(ToVectorAndPrefReducer.class);
    partialMultiply.setMapOutputKeyClass(VarIntWritable.class);
    partialMultiply.setMapOutputValueClass(VectorOrPrefWritable.class);
    //两个map在这里reduce
    partialMultiply.setReducerClass(ToVectorAndPrefReducer.class);
    partialMultiply.setOutputFormatClass(SequenceFileOutputFormat.class);
    partialMultiply.setOutputKeyClass(VarIntWritable.class);
    partialMultiply.setOutputValueClass(VectorAndPrefsWritable.class);
    partialMultiplyConf.setBoolean("mapred.compress.map.output", true);
    partialMultiplyConf.set("mapred.output.dir", partialMultiplyPath.toString());

我们看到这个job有点奇怪,为什么呢?因为他有两个inputPath的设置,那么我们就可以知道它是两个map然后将数据总和reduce。
两个map分别是:SimilarityMatrixRowWrapperMapper、UserVectorSplitterMapper
通过之上的代码可以看到,SimilarityMatrixRowWrapperMapper的输入数据是之前我们RecommenderJob得到的相似矩阵,而UserVectorSplitterMapper的输入数据是我们再笔记1中的预备job中得到的user-item,pref矩阵。
首先我们看SimilarityMatrixRowWrapperMapper的代码:

public final class SimilarityMatrixRowWrapperMapper extends
    Mapper<IntWritable,VectorWritable,VarIntWritable,VectorOrPrefWritable> {
   

  private final VarIntWritable index = new VarIntWritable();
  private final VectorOrPrefWritable vectorOrPref = new VectorOrPrefWritable();

  @Override
  protected void map(IntWritable key,
                     VectorWritable value,
                     Context context) throws IOException, InterruptedException {
    Vector similarityMatrixRow = value.get();
    /* remove self similarity */
    //这里它将item关于自己的相似度设为NaN,其实并不是这一步remove
    //而是通过设置自己的相似度为最大在之后的计算中不在考虑,通过这种间接的方法remove
    similarityMatrixRow.set(key.get(), Double.NaN);

    index.set(key.get());
    vectorOrPref.set(similarityMatrixRow);
    context.write(index, vectorOrPref);
  }

这里有一个小细节,我们可以看到,vectorOrPref的类型已经不是普通的Vector了,而是变为了VectorOrPrefWritable,那么这个VectorOrPrefWritable是什么呢?我们跟进代码可以看到:

public final class VectorOrPrefWritable implements Writable {
   

  private Vector vector;
  private long userID;
  private float value;

  ...
  void set(Vector vector) {
    this.vector = vector;
    this.userID = Long.MIN_VALUE;
    this.value = Float.NaN;
  }

可以看到这个类型拥有三个成员,分别是一个Vector,一个long存放userID,一个float存放Value,而我们之上的map中的vectorOrPref对Vector进行赋值,其他两个变量的值根据set函数可以看到设置成了极小。接下来我们看另一个map,UserVectorSplitterMapper:

public final class UserVectorSplitterMapper extends
    Mapper<VarLongWritable,VectorWritable, VarIntWritable,VectorOrPrefWritable> {
   

  ...

  @Override
  protected void map(VarLongWritable key,
                     VectorWritable value,
                     Context context) throws IOException, InterruptedException {
    long userID = key.get();

    log.info("UserID = {}", userID);

    if (usersToRecommendFor != null && !usersToRecommendFor.contains(userID)) {
      return;
    }

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值