接上篇blog,继续分析。接下来要调用代码如下:
// Should document frequency features be processed if (shouldPrune || processIdf) { docFrequenciesFeatures = TFIDFConverter.calculateDF(new Path(outputDir, tfDirName), outputDir, conf, chunkSize); }
首先不看shouldPrune变量,单单看processIdf变量来说,这个变量肯定是true的,所以肯定要执行if里面的部分了,这个是计算DF的函数(单单就单词意思来说);
打开这个函数可以看到主要进行了两个操作:
startDFCounting(input, wordCountPath, baseConf); return createDictionaryChunks(wordCountPath, output, baseConf, chunkSizeInMegabytes);
第一个是什么计数,第二个是产生一个dictionary 块;怎么感觉和前面的 Twenty Newsgroups Classification任务之二seq2sparse(2)一模一样,额,好吧,确实有很多相同的地方,应该说基本是一样的,可以参考前面的来分析;但是有点区别的地方是,首先计数的Job里面的Mapper,TermDocumentCountMapper有这样的一句:
private static final IntWritable TOTAL_COUNT = new IntWritable(-1);
while (it.hasNext()) { Vector.Element e = it.next(); context.write(new IntWritable(e.index()), ONE); } context.write(TOTAL_COUNT, ONE);
可以看到在最后还写多了一句、这里先明确几个变量,全部的单词个数有93563个,一共的文件个数(或者说vector个数)有18846个;看这个job的详细信息:
这里就再次说明了reduce接受的key的个数比单词数多了一个即93564;
其次,在新建dictionary块的时候也有不同的地方,首先调用的类是TFIDFConverter。但是其操作基本一样,看到下面的代码:
if (key.get() >= 0) { freqWriter.append(key, value); } else if (key.get() == -1) { vectorCount = value.get(); } featureCount = Math.max(key.get(), featureCount); } featureCount++; Long[] counts = {featureCount, vectorCount}; return new Pair<Long[], List<Path>>(counts, chunkPaths);
这里确实是有多一个key为-1的记录,然后featureCount应该是记录vector的key值,在++之前应该是18846,在++之后就是18847了,所以counts应该为[18847,93564];这个可以通过设置断点来查看;具体下次分析,还有下面两个Job其实应该是和seq2sparse(3)、(4)类似了,只是分析的数据的vector由单词转换为了数值,其他都一样,这样分析之后,后面两个Job就很简单了,然后就是最后的算法精髓了。然后就这个算法就分析完了吧(感觉看了好久的样子。。。)
分享,快乐,成长
转载请注明出处:http://blog.csdn.net/fansy1990