用 Hadoop 实现共生矩阵计算

共生矩阵可以被描述为对一个事件的跟踪,并且给出了关于其他可能发生的事件的某个时间或者空间上的窗口。在这篇文章中,“事件”是指在文本中发现的个别单词,我们将追踪出现在“窗口”内的其他单词相对于目标单词的位置。以“敏捷的棕色狐狸跳过那条懒惰的狗”为例,有两个窗口值。“跳”的共生词为[棕色,狐狸,过,那条]。共生矩阵可以被应用到其他需要调查“该”事件何时发生以及同一时间可能发生了其他什么事件的领域。要建立文本共生矩阵,我们就要采用第三章“用MapReduce实现数据密集型文本处理”中提到的Stripes算法。用于创建我们共生矩阵的正文是 威廉莎士比亚全集

实现pairs方法是很直接明了的,当map功能被调用时会遍历每行传递的值,我们将分隔一个区间创建一个String数组。下一步将会去构造两个循环。外部循环在数组中迭代遍历每个语句,内部循环将迭代"neighbors"的当前语句。许多内部循环的迭代被我们"window"捕获neighbor的当前语句所影响。在内部循环每个迭代的下面,我么将发布一个WordPair项目(两部分组成:当前语句在neighbor语句在右边)作为键,计数的一个作为值,下面是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 }

Reducer对Pairs实现将简单计算出给定WordPair键的总和

01 public class PairsReducer extendsReducer<WordPair,IntWritable,WordPair,IntWritable> {
02     private IntWritable totalCount = new IntWritable();
03     @Override
04     protected void reduce(WordPair key, Iterable<IntWritable> values, Context context) throws IOException, 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方法去共生同样是很直接明了的,方法相同,但所有的"neighbor"语句被放在一个HashMap中时就用neighbor语句作为键,整数count作为值。当所有的值遍历完后被放在一个给定命令下时(外部循环的下面),word和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 }
由于需要迭代所有maps的集合 Reducer对Stripes方法 稍微涉及多点,然后对每个集合,迭代map中的所有值。 


1 public class StripesReducer extends Reducer<Text, MapWritable, Text, MapWritable> {
2     private MapWritable incrementingMap = new MapWritable();
3  
4     @Override
5     protected void reduce(Text key, Iterable<MapWritable> values, Context context) throwsIOException, InterruptedException {
6         incrementingMap.clear();
7         for (MapWritable value : values) {
8             addAll(value);

结论

现在来比较两种算法,看得出相较于Stripes算法,Pairs算法会产生更多的键值对。而且,Pairs 算法捕获到的是单个的共生事件而Stripes 算法能够捕获到所有的共生事件。Pairs算法和Stripes算法的实现都非常适宜于使用Combiner。因为这两种算法实现产生的结果都是可交换与可结合【译者注:可使用combiner的数据必须能够满足交换律与结合律,忘了这是那篇文档中提出的了】的,所以我们可以简单地重用reducer作为Combiner。如前所述,共生矩阵不仅仅能应用于文本处理,它会是我们手中的一项重要武器。谢谢你读到这里。

参考资料



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值