MapReduce在搜索引擎中一些应用

来源:互联网 发布:弱智吧 知乎 编辑:程序博客网 时间:2024/05/16 05:51

word-doc矩阵

在进行文件分类或文档检索的时候,我们通常需要建立一个word-doc矩阵,来记录每个词在每篇文档中出现的次数。

class Mappermethod map(docid id,doc d)foreach term in dEmit(pair(term,id),1)

一种更高效的方法是在mapper侧进行聚合。

class Mappermethod map(docid id,doc d)H := new AssociativeArrayforeach term in dH{term} := H{term}+1foreach term in HEmit(pair(term,id),H{term})

图的宽度优先遍历

现代的爬虫一般采用宽度优先的规则来遍历网络。还有在Dijkstra算法中也是一种宽度优先的规则--每发再一个新的最近点,就更新与之相邻的节点的dist。我们可以用MapReduce迭代的方式来实现Dijkstra算法。每轮迭代运行一次Map-Reduce,最多迭代N次,N是图中节点的个数。用邻接链表来存储图。算法开始时,起始节点的dist赋0,其余的节点dist赋无穷大。先考虑简单的情形--每条边的权值都是1。

class Mappermethod map(nid n,node N)d := N.distanceEmit(nid n,N)//pass along graph structureforeach nodeid m in N.AdjacencyListEmit(nid m,d+1)//Emit distances to reachable nodesclass Reducermethod reduce(nid m,[d1,d2,...])minDist := infiniteM := NULLforeach d in [d1,d2,...]if IsNode(d)M := d//recover graph structureelse if d<minDist//lookup for shortest distanceminDist := dM.distance := minDist//update shortest distanceEmit(nid m,node M)

在迭代式的Map-Reduce程序设计中,需要有一个driver来控制迭代的进行,检查终止条件是否满足。在reducer中如果所有node的minDist都没有更新,更迭代终止。

上面的代码只算出了源节点到其他节点的最短路程,并没有记录下最短路径,所以我们需要在更新minDist的同时记录下它的上一个节点,mapper在输出(nid,dist)时也应该输出与dist对应的是哪个节点。

上面假设任意节点间的距离都是1,当是任意值r时,只需要在mapper中输出(nid m,d+r)就可以了。

跟单进程的Dijkstra算法比起来,这种Map-Reduce版的算法显然计算量大了许多,因为它每次迭代都要去检查每一个节点的邻居的dist是否需要更新;而单进程的Dijkstra算法通过维持一个优先队列,它每次迭代只需要检查队首元素的邻居的dist是否需要更新。在Hadoop中,mapper和reducer通信方式非常受限,我们无法维持一个像优先队列这样一种全局的数据结构。正因如此,Map-Reduce不适合于处理大规则,稠密图。

Page Rank

在网页排序算法中Page Rank可谓鼎鼎有名--虽然它只是Google对网页进行排序的上千种因素中的一个。该算法认为一个网页的重要度,由它链接到它的的网页的重要度来决定。网页重要度公式为:

|G|中整个网络当中节点的总个数,α是随机跳转因子,L(n)是所有铰接到网页n的网页的集合,C(m)是网页m的出度。在网页m上的一个冲浪者它以1/C(m)的概率进入网页n。如何理解加式的第1项呢?一个冲浪者在浏览网页时并不总是点击超链接进行下去的,他也有可能在地址栏随机地输入了一个网址,一下子跳转到了一个完全不相关的网页。

Page Rank算法迭代地计算每个网页的重要度,实际上就是一种宽度优先遍历的方法。一个网页从它的所有incoming网页中“收集”重要度,很自然地用reducer来完成。开始时给网络图上的每个节点赋一个服从[0,1]的均匀分布的随机值作为其重要度。Map-Reduce不断地迭代,直到每个网页的重要度都不再变化为止。

下面的代码简化起见,没有考虑公式中的第一项。

class Mappermethod map(nid n,node N)p := N.PageRank/|N.AdjacencyList|Emit(nid n,N)//pass along graph structureforeach nodeid m in N.AdjacencyListEmit(nid m,p)class Reducermethod reduce(nid m,[p1,p2,...])M := NULLs := 0foreach p in [p1,p2,...]if IsNode(p)M := ps := M.PageRankelses := s+pM.PageRank := sEmit(nid m,node M)

Graph Structure被mapper抛出,又被reducer写入磁盘,这样它从上一次迭代又传递一了下一次迭代。

 

HMM算法

当年李开复搞语音识别用的就是隐马尔可夫算法,HMM在中文分词和词性标注中也大显威力。

EM算法也是Machine Learning中的重要算法之一,比如HMM模型参数的确立、高斯混合模型参数的确立都要用到它。

 

K-means算法

K-means是一种古老且经典的聚类算法,至今仍广泛使用。

class Mappermethod setup()Centers[K] := ReadFromFilemethod map(docid id,doc d)H := new AssociativeArrayforeach data in dCenters[index] := NearestCenterToDatac := H{index}.lefts := H{index}.rightH{index} := Pair(c+1,s+data)foreach integer i in HEmit(i,H{i})class Reducermethod reduce(integer i,pairs [p1,p2,...])s := 0c := 0foreach pair in [p1,p2,...]s := s+pair.rightc := c+pair.leftEmit(i,s/c)