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

  下面来看一下df-count目录与freqency.file-n文件的生成过程。df-count目录中记录的是词汇的文档频率,并用了一个技巧统计了文档的数目,就是在对tf-vectors目录中每个文档tf向量进行处理的时候对每个文档插入了<-1, 1>这样一个键值对,这样可以再reduce时得出词汇的文档频率同时得出文档数目。freqency.file-n中把df-count中的内容分块,保证每一个向量在计算都可以在内存中进行。

  先从startDFCounting()函数开始,它运行了一个MapReduce Job,会生成df-count:

   job.setMapperClass(TermDocumentCountMapper.class);
    job.setInputFormatClass(SequenceFileInputFormat.class);
    job.setCombinerClass(TermDocumentCountReducer.class);
    job.setReducerClass(TermDocumentCountReducer.class);
    job.setOutputFormatClass(SequenceFileOutputFormat.class);

  Map阶段由TermDocumentCountMapper负责,Reduce阶段由TermDocumentCountReducer负责。

Mapper:

 protected void map(WritableComparable<?> key, VectorWritable value, Context context)
    throws IOException, InterruptedException {
    Vector vector = value.get();
    Iterator<Vector.Element> it = vector.iterateNonZero();
    //将每个Vector中词汇打散并记频率为1,由MapReduce将数据排序组合传递给reducer
    while (it.hasNext()) {
      Vector.Element e = it.next();
      context.write(new IntWritable(e.index()), ONE);
    }
    //这个是为了统计文档数用的,-1来表示
    context.write(TOTAL_COUNT, ONE);
  }
Reducer:

 protected void reduce(IntWritable key, Iterable<LongWritable> values, Context context)
    throws IOException, InterruptedException {
    long sum = 0;
    //这里并没有区分-1那个值,也就是文档当作一个词来处理了,reduce之后-1键所对应的值就是文档数目
    for (LongWritable value : values) {
      sum += value.get();
    }
    context.write(key, new LongWritable(sum));
  }

  这样就完成了df-count目录的生成,一个序列文件里面记录了词的文档频率与文档数目。

createDictionaryChunks()函数就不再过多说了,与DocumentVectorizer中的功能差不多就是把一个大的文件分开方便在内存中处理其返回的值是一个数值对:Pair<Long[], List<Path>>,long型数组中有两个元素,第一个为词汇的个数,第二个为文档向量数目;List<Path>中保存了不同的trunk路径。

 

以上为个人理解,有问题大家多多交流。。。

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