用 Hadoop 计算共生矩阵
2013-01-27 23:39
357 查看
本文另一地址请见用 Hadoop 计算共生矩阵
本文译自Calculating A Co-Occurrence Matrix with Hadoop
本文是《Data-Intensive Text Processing with MapReduce》提到的MapReduce算法的系列文章的延续。这次我们会使用语料库建立一个单词共生矩阵。
所谓共生矩阵可以描述为对于某种事件,给予一个特定的时间或者空间限制,然后记录在这种情况下会发生的事件。本文中的“事件”指的是在文本中出现的单词,我们要记录在限制条件内其他词的出现情况,这个限制条件是指其他词相对于目标单词的位置。例如,考虑这句话“The quick brown fox jumped over the lazy dog”。限制条件是2,jumped这个单词满足条件的共生是 [brown,fox,over,the]。共生矩阵可以应用于需要调查在某个事件发生时同时还发生了什么时间的情况。我们将使用《Data-Intensive Text Processing with MapReduce》书中第三章提到过的Stripes算法和Pairs算法来建立文本共生矩阵。用以建立共生矩阵的文本资料来自《莎士比亚全集》。
Pairs算法中的Reducer只要简单的将作为key的同一WordPair的计数加和。
Stripes算法的Reducer稍微有点复杂,因为我们要遍历每个key的所有map,包括遍历每个map中的所有值。
Hadoop: The Definitive Guide by Tom White
Source Code and Tests from blog
Hadoop API
MRUnit 用来测试Apache Hadoop mapreduce
本文译自Calculating A Co-Occurrence Matrix with Hadoop
本文是《Data-Intensive Text Processing with MapReduce》提到的MapReduce算法的系列文章的延续。这次我们会使用语料库建立一个单词共生矩阵。
所谓共生矩阵可以描述为对于某种事件,给予一个特定的时间或者空间限制,然后记录在这种情况下会发生的事件。本文中的“事件”指的是在文本中出现的单词,我们要记录在限制条件内其他词的出现情况,这个限制条件是指其他词相对于目标单词的位置。例如,考虑这句话“The quick brown fox jumped over the lazy dog”。限制条件是2,jumped这个单词满足条件的共生是 [brown,fox,over,the]。共生矩阵可以应用于需要调查在某个事件发生时同时还发生了什么时间的情况。我们将使用《Data-Intensive Text Processing with MapReduce》书中第三章提到过的Stripes算法和Pairs算法来建立文本共生矩阵。用以建立共生矩阵的文本资料来自《莎士比亚全集》。
Pairs算法
实现pairs算法十分简单。map函数每调用一次就传入一行,按照空格把传入的行切分成字符串数组。下一步是建立两层循环。外层循环数组中的每个词,内层循环遍历当前词的邻接词。内层循环的迭代次数取决于需要捕捉的当前词的邻接距离。在内层循环的每次迭代的最后,我们会输出一个WordPair对象(由两个词组成,当前词居左,邻接词居右)作为key,该组词的出现频度作为值。下面是pairs算法的实现代码:01 | public class PairsOccurrenceMapper extends Mapper<LongWritable, Text, WordPair, IntWritable> { |
02 | private WordPair wordPair = new WordPair(); |
03 | private IntWritable ONE = new IntWritable(1); |
04 |
05 | @Override |
06 | protected void map(LongWritable key, Text value, Context context) throwsIOException, InterruptedException { |
07 | int neighbors = context.getConfiguration().getInt("neighbors", 2); |
08 | String[] tokens = value.toString().split("\\s+"); |
09 | if (tokens.length > 1) { |
10 | for (int i = 0; i < tokens.length; i++) { |
11 | wordPair.setWord(tokens[i]); |
12 |
13 | int start = (i - neighbors < 0) ? 0 : i - neighbors; |
14 | int end = (i + neighbors >= tokens.length) ? tokens.length - 1 : i + neighbors; |
15 | for (int j = start; j <= end; j++) { |
16 | if (j == i) continue; |
17 | wordPair.setNeighbor(tokens[j]); |
18 | context.write(wordPair, ONE); |
19 | } |
20 | } |
21 | } |
22 | } |
23 | } |
01 | public class PairsReducer extends Reducer<WordPair,IntWritable,WordPair,IntWritable> { |
02 | private IntWritable totalCount = new IntWritable(); |
03 | @Override |
04 | protected void reduce(WordPair key, Iterable<IntWritable> values, Context context) throwsIOException, InterruptedException { |
05 | int count = 0; |
06 | for (IntWritable value : values) { |
07 | count += value.get(); |
08 | } |
09 | totalCount.set(count); |
10 | context.write(key,totalCount); |
11 | } |
12 | } |
Stripes算法
共生矩阵中的stripes算法实现一样很简单。 不过与pairs算法不同的是,每个词的所有相邻词被存储在一个hashmap中,以该邻接词为key,词的出现频数为值。当循环遍历完一个词的所有邻接词之后,这个词和与之关联的hashmap被输出。下面是stripes算法的实现代码:01 | public class StripesOccurrenceMapper extends Mapper<LongWritable,Text,Text,MapWritable> { |
02 | private MapWritable occurrenceMap = new MapWritable(); |
03 | private Text word = new Text(); |
04 |
05 | @Override |
06 | protected void map(LongWritable key, Text value, Context context) throwsIOException, InterruptedException { |
07 | int neighbors = context.getConfiguration().getInt("neighbors", 2); |
08 | String[] tokens = value.toString().split("\\s+"); |
09 | if (tokens.length > 1) { |
10 | for (int i = 0; i < tokens.length; i++) { |
11 | word.set(tokens[i]); |
12 | occurrenceMap.clear(); |
13 |
14 | int start = (i - neighbors < 0) ? 0 : i - neighbors; |
15 | int end = (i + neighbors >= tokens.length) ? tokens.length - 1 : i + neighbors; |
16 | for (int j = start; j <= end; j++) { |
17 | if (j == i) continue; |
18 | Text neighbor = new Text(tokens[j]); |
19 | if(occurrenceMap.containsKey(neighbor)){ |
20 | IntWritable count = (IntWritable)occurrenceMap.get(neighbor); |
21 | count.set(count.get()+1); |
22 | }else{ |
23 | occurrenceMap.put(neighbor,new IntWritable(1)); |
24 | } |
25 | } |
26 | context.write(word,occurrenceMap); |
27 | } |
28 | } |
29 | } |
30 | } |
01 | public class StripesReducer extends Reducer<Text, MapWritable, Text, MapWritable> { |
02 | private MapWritable incrementingMap = new MapWritable(); |
03 |
04 | @Override |
05 | protected void reduce(Text key, Iterable<MapWritable> values, Context context) throwsIOException, InterruptedException { |
06 | incrementingMap.clear(); |
07 | for (MapWritable value : values) { |
08 | addAll(value); |
09 | } |
10 | context.write(key, incrementingMap); |
11 | } |
12 |
13 | private void addAll(MapWritable mapWritable) { |
14 | Set<Writable> keys = mapWritable.keySet(); |
15 | for (Writable key : keys) { |
16 | IntWritable fromCount = (IntWritable) mapWritable.get(key); |
17 | if (incrementingMap.containsKey(key)) { |
18 | IntWritable count = (IntWritable) incrementingMap.get(key); |
19 | count.set(count.get() + fromCount.get()); |
20 | } else { |
21 | incrementingMap.put(key, fromCount); |
22 | } |
23 | } |
24 | } |
25 | } |
结论
现在来比较两种算法,看得出相较于Stripes算法,Pairs算法会产生更多的键值对。而且,Pairs 算法捕获到的是单个的共生事件而Stripes 算法能够捕获到所有的共生事件。Pairs算法和Stripes算法的实现都非常适宜于使用Combiner。因为这两种算法实现产生的结果都是可交换与可结合【译者注:可使用combiner的数据必须能够满足交换律与结合律,忘了这是那篇文档中提出的了】的,所以我们可以简单地重用reducer作为Combiner。如前所述,共生矩阵不仅仅能应用于文本处理,它会是我们手中的一项重要武器。谢谢你读到这里。参考资料
Data-Intensive Processing with MapReduce by Jimmy Lin and Chris DyerHadoop: The Definitive Guide by Tom White
Source Code and Tests from blog
Hadoop API
MRUnit 用来测试Apache Hadoop mapreduce
相关文章推荐
- hadoop第一个计算任务wordcount的运行
- Hadoop-- 海量文件的分布式计算处理方案
- hadoop计算平均值
- HaLoop——适用于迭代计算的Hadoop
- 分布式计算开源框架Hadoop介绍
- 分布式计算开源框架Hadoop介绍
- 大数据、Hadoop和云计算
- Hadoop系列之MapReduce(分布式计算测试)
- 云计算(二)- Hadoop2.2 集群安装
- hadoop计算框架shuffler
- 用 Hadoop 计算共生矩阵
- 云计算学习笔记---异常处理---hadoop问题处理ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.lang.NullPoin
- Hadoop对计算节点TaskTracker的惩罚机制
- 云计算的核心技术之Hadoop
- 分布式计算框架Hadoop介绍(1)
- 注意地方hadoop中的pi值计算
- 分布式计算开源框架Hadoop介绍1
- 利用hadoop计算文件中的最大值
- Hadoop计算框架shuffle过程详解
- Spark、HPCC与Hadoop计算模型之趣味比较