Mahout文本聚类学习之TFIDFConverter类(3)

  接下来是最重要的通过df-count与tf-vectors来生成tfidf-vectors的过程了。这一过程通过makePartialVectors()与mergePartialVectors()来实现。通过循环调用makePartialVectors生成tfidf vector的每个部分,这个过程可以将上一步分块的frequency.file-n加载到内存中通过MapReduce来完成,再通过mergePartialVectors运行MapReduce任务来高效合并得出最终的tfidf-vectors。

  makePartialVectors()运行MapReduce Job将tfidf向量的每一部分存入不两只的临时目录中。

   job.setMapperClass(Mapper.class);
    job.setInputFormatClass(SequenceFileInputFormat.class);
    job.setReducerClass(TFIDFPartialVectorReducer.class);
    job.setOutputFormatClass(SequenceFileOutputFormat.class);

从代码中可以看到,Mapper只是把tf-vectors中的向量读出,排序后交与TFIDFPartialVectorReducer进行处理。再来看下Reducer做了什么:

 protected void reduce(WritableComparable<?> key, Iterable<VectorWritable> values, Context context)
    throws IOException, InterruptedException {
    Iterator<VectorWritable> it = values.iterator();
    if (!it.hasNext()) {
      return;
    }
    //取到文档的tf向量
    Vector value = it.next().get();
    Iterator<Vector.Element> it1 = value.iterateNonZero();
    //生成tfidf向量,维数为featureCount
    Vector vector = new RandomAccessSparseVector((int) featureCount, value.getNumNondefaultElements());
    while (it1.hasNext()) {
      Vector.Element e = it1.next();
      if (!dictionary.containsKey(e.index())) {
        continue;
      }
      //得到词的文档频率
      long df = dictionary.get(e.index());
      if (maxDf > -1 && (100.0 * df) / vectorCount > maxDf) {
        continue;
      }
      if (df < minDf) {
        df = minDf;
      }
      //通过调用tfidf算法来计算向量中每一维数据的tfidf值参数为tf,df,文档数,词总数
      vector.setQuick(e.index(), tfidf.calculate((int) e.get(), (int) df, (int) featureCount, (int) vectorCount));
    }
    if (sequentialAccess) {
      vector = new SequentialAccessSparseVector(vector);
    }
    
    if (namedVector) {
      vector = new NamedVector(vector, key.toString());
    }
    
    VectorWritable vectorWritable = new VectorWritable(vector);
    context.write(key, vectorWritable);
  }

这样就得到了所有文档的部分维的tfidf值,输出到临时目录中。下一步进行合并操作,下面代码是merg job的配置一部分:

   job.setMapperClass(Mapper.class);
    job.setInputFormatClass(SequenceFileInputFormat.class);
    job.setReducerClass(PartialVectorMergeReducer.class);
    job.setOutputFormatClass(SequenceFileOutputFormat.class);
    job.setNumReduceTasks(numReducers);

ParialVectorMergeReducer是主要的了这个在计算tf向量时已经介绍就不再细说了,到此为此生成了所有文档的tfidf向量。

posted @ 2012-09-28 16:49  answer0107  阅读(355)  评论(0)    收藏  举报