我正在开发著名的 WordCount 程序的一个稍微改进的版本,它应该输出该单词占书中的百分比。例如:
...
war 0.00002332423%
peace 0.0034234324%
...
基本上,我需要计算所有单词的数量,计算每个单词的出现次数,然后将这组值除以总数。所以至少应该有两个工作:
工作1
input
目录并生成两个输出目录:output1
和 output2
(word, 1)
对写入output1
,将("total_count", 1)
对写入output2
(word, n)
中的 output1
相加,计算 ("total_count", N)
中的
output2
工作2
output1
和 output2
作为输入文件夹,将结果写入 output3
total_count
,将结果写入output3
我的问题:
我想避免两次查看原始输入,这就是为什么我试图计算 Job1 中的字数和总计数。但我不明白如何避免混淆一个输出中的结果。我尝试过使用
MultipleOutputs
但在这种情况下,映射器的结果不会进入减速器。Job2需要多个输入,而且需要先读取
output2
,因为没有总计数,从output1
读取结果是没有用的。我觉得这是使用 MapReduce 的错误方式(我们不应该使用任何类型的同步),但没有看到正确的方式。Job2 中的 Mapper 没有做任何有用的事情,只会浪费处理器时间。
关于使用单个作业的想法:
total_count
可以从第一个作业的map阶段计算出来。其实已经算MAP_OUTPUT_RECORDS
了。这是所有地图输出 (key, value)
对的总和。因此,如果您始终将 1 作为值,那么这个总和就是您想要的,即文档中的单词总数(包含重复)。
现在,我不知道你是否可以在减速器的配置中获得这个计数器。然后,您可以为每个单词输出
(word, wordCount/MAP_OUTPUT_RECORDS)
对。我认为你可以通过以下方式做到这一点:
新API:
context.getCounter("org.apache.hadoop.mapred.Task$Counter", "MAP_OUTPUT_RECORDS").getValue();
旧 API:
reporter.getCounter("org.apache.hadoop.mapred.Task$Counter", "MAP_OUTPUT_RECORDS").getValue();
一种非优化的方法是创建一个特殊的单词(如“00000”)并用它来计算所有单词的数量。映射器 1 会为其遇到的每个单词写出 (word, 1) 和 ("00000", 1)。然后,Reducer 1 将对所有单词进行计数并计算总数(“00000”的计数)。
下一个作业将有一个直通映射器,并且减速器将计算百分比。这里的技巧是(1)有一个减速器,(2)选择“00000”单词,以便它在所有其他单词之前排序。通过这种方式,总数首先传递到Reducer 2,并且对于所有后续的字数计数都是已知的。
Yurii,可以帮我解决百分比词的问题吗?
我需要两项链接工作。
谢谢