昨晚上不想做其他的事,突然想起来好久都没更新博客了,shell也差不多学完了,只不过学习的时候都是只带着书出去了,改天总结总结。Hadoop么,黄宜华老师讲完了,自己也马马虎虎快学完了,也是没总结,那今天就写下前段时间写的一个关于英文Wiki的PageRank代码吧。

PageRank的ABC

什么是PageRank

PageRank是一种在搜索引擎中根据网页之间相互的链接关系计算网页排名的技术。

PageRank是Google用来标识网页的等级或重要性的一种方法。其级别从1到10级,PR值越高说明该网页越受欢迎(越重要)。

PageRank的基本设计思想和原则

被许多优质网页所链接的网页,多半也是优质网页。

一个网页要想拥有较高的PR值的条件:

  1. 有很多网页链接到它;
  2. 有高质量的网页链接到它

PageRank的简化模型

可以把互联网上的各个网页之间的链接关系看成一个有向图。

对于任意网页Pi,它的PageRank值可表示为:

其中Bi为所有链接到网页i的网页集合,Lj为网页j的对外链接

简化模型面临的缺陷

实际的网络超链接环境没有这么理想化,PageRank会面临两个问题:

  1. Rank leak:就是有的网页没有链出网页,使用上面的公式时,循环几次后所有的PageRank值都变为0
  2. Rank sink:整个网页图中的一组紧密链接成环的网页如果没有外出的链接就产生Rank sink,即经过若干次循环后不在环中的网页的PR值会变为0

解决简化模型的缺陷的解决办法——采用随机浏览模型:

假定一个上网者从一个随机的网页开始浏览

上网者不断点击当前网页的链接开始下一次浏览

但是,上网者最终厌倦了,开始了一个随机的网页

随机上网者用以上方式访问一个新网页的概率就等于这个网页的PageRank值

这种随机模型更加接近于用户的浏览行为

采用随机浏览模型后的PR值计算公式变为

其中d为按照超链进行浏览的概率,1-d即为用户随机跳转一个新网页的概率,显然跳转到每个网页的概率为(1-d)/N,N为所有网页的数目。

依据上述公式,一般经过10次左右的计算,每一个网页可以得到一个稳定的PR值(数学证明使用马尔可夫链收敛定理,不太懂,有兴趣的同学可以关注下)

使用MapReduce实现PageRank

显然这样一个需要进行大量累加计算的工作是适合用MapReduce来做的,那么怎么做呢?分三个阶段完成这个事情:

Phase1: GraphBuilder

建立网页之间的超链接图

Phase2: PageRankIter

迭代计算各个网页的PageRank值

Phase3: RankViewer

按PageRank值从大到小输

具体设计:

En_wiki中每行对应于一个页面,页面的标题包含在“&lttitle&gtName of thearticle&lt/title&gt”中,每个页面的链出标题在一对双中括号中("[[Name of other article]]"),我们需要做的就是用PageRank算法给出每个页面的重要性,并按重要程度从高到低输出。首先要做的就是构建每个页面的链接关系图,这个工作我们GraphBuilder类来实现,给出的结构类似于图的邻接表表示方式;第二步需要做的工作就是用PageRank算法经过一定次数的迭代,得出最终每个页面的PRValue,具体算法在PageRankler类中实现;第三步需要将结果展现出来,并按“PRvalue           title”的格式降序输出,类PageRankViewer实现该功能;最后,需要组织整个算法,这是main函数完成的功能。

以下具体阐述每个类的具体实现:

1.           整体类视图

2.           GraphBuilder类

map中完成链接图的构造。首先需解决的问题就是如何提取出title及linktitle,我们使用正则表达式来完成:"(?<=&lttitle&gt)(.*?)(?=&lt/title&gt)"来完成对title的匹配,使用"(?<=\\[\\[)(.+?)(?=\\]\\])"来完成对linktitle的匹配。此处需要主要注意的在第二个匹配模式中,由于'['和']'属于正则表达式中的元字符,因此需要对其进行转义,在Java语言的字符串中还要对转义字符进行一次转义,因此会出现两个反斜杠。提取完成之后,key设为title,初始PRValue和链出列表以“PRValue%%%%link1   link2      link3      ...”的格式作为value发射出去。key和value的类型都是Text。

reduce阶段不需要做额外的工作,将map阶段给的键值队原样发射出去即可,可以使用默认的reduce来做,此处还是自己实现。

main11函数完成整个job的参数设置及运行该job,如果使用默认的reduce,此处需要具体设置map输出的key、value以及输出的key、value的类型,否则会出现一个类型不匹配的错误。由于输出文件还要在下一个job中作为输入,因此输出类型设为二进制类型(SequenceFileOutputFormat),在下一步中奖输入格式设为二进制后,map可以自己识别出key和value。另外需要做的工作就是,如果输出目录存在需要将其删除,然后开始执行job。

3.           PageRankler类

map的输入和输出的key和value都为Text类型,需要做的工作是继续维护图的结构以及“分饼”工作,即将自己的PRValue均分到每个链出的title上。从读入的value中得到自己的PRValue和链出的title,由于value的格式为:“PRValue%%%%%%link1 link2      link3      ...”因此用两次split就可以得到PRValue和linktitle数组。对linktitle数组中的每个元素都分配PRValue并发射出去,发射的key为linkTitle,value为PRValue/linktitle.length(),最后将图的结构“link1       link2      link3      …”发射出去。

需要自己定制combiner,因为一个页面中出现相同的linktitle是有可能的。如果发来的图结构,不处理直接发射出去,如果不是,进行简单的累加后发射。

redece阶段对title从每个链接源得到的PR值进行合并得到PRValue,然后按照公式:newPR = (1 - d) + d * PRvalue得到newPR,注意此处随机浏览的概率设置为1-d而不是(1-d)/N,主要是相对非常大的N,(1-d)/N小到可以忽略。刚开始的时候,我试图在GraphBuilder中的map中得到N,设置了一个全局静态变量,在map处理一行的时候对该变量加一,在本机上这个机制是有作用的,但是到集群上之后,得到的所有PRValue都是无穷大,后来领悟到:map是在各个节点上做的,所以N值不会变化,而是初始的值0,后来自己想写一个job得到N,发现没有任何意义,舍弃之。得到新的PRValue后,将value设为“PRValue%%%%link1       link2      link3      ...”发射,供下轮job使用。

isDouble函数完成对一个字符串是否为一个浮点数进行判断,这个函数用在map阶段,用于判断一个value是图结构还是分到的PRValue。

main11对整个job进行设置,输入输出格式都设为二进制,其他的与上个阶段的main11做的事基本相同。

4.           PageRankViewer类

map阶段所做的事是将value中的PRValue提取出来,然后将key设为PRValue,value设为title,发射。

因为要求按降序输出,故此处还要写自己的Comparator,只需要返回父类的相关函数的返回值的相反值即可。

main11函数设置相关的参数和输入输出值的类型,基本同上个类。

5.           main函数

main函数完成对所有job流程的控制,包括设置输入输出路径以及参数检查,还有设置PageRank的迭代次数等等。

运行结果:

本次实验将所有title的初始PRValue设置为0.5,阻尼系数设置为0.85,PageRank迭代次数设为10次,在集群上的运行结果的前30个title列表及其PRValue值如下图所示:

代码就不贴了,按照这个思路实现起来应该很简单的

转载于:https://www.cnblogs.com/BigBesom/archive/2012/05/15/2500891.html

Hadoop学习系列之PageRank相关推荐

  1. Hadoop学习系列之Hadoop、Spark学习路线(很值得推荐)

    Hadoop学习系列之Hadoop.Spark学习路线(很值得推荐) 文章出自:http://www.cnblogs.com/zlslch/p/5448857.html 1 Java基础: 视频方面: ...

  2. 大数据Hadoop学习系列之Hadoop、Spark学习路线

    1 Java基础: 视频方面:推荐毕老师<毕向东JAVA基础视频教程>. 学习hadoop不需要过度的深入,java学习到javase,在多线程和并行化多多理解实践即可. 书籍方面:推荐李 ...

  3. Hadoop学习系列之Hadoop、Spark学习路线

    1 Java基础: 视频方面:推荐毕老师<毕向东JAVA基础视频教程>. 学习hadoop不需要过度的深入,java学习到javase,在多线程和并行化多多理解实践即可. 书籍方面:推荐李 ...

  4. Hadoop学习笔记系列文章导航

    一.为何要学习Hadoop? 这是一个信息爆炸的时代.经过数十年的积累,很多企业都聚集了大量的数据.这些数据也是企业的核心财富之一,怎样从累积的数据里寻找价值,变废为宝炼数成金成为当务之急.但数据增长 ...

  5. 大数据学习系列之八----- Hadoop、Spark、HBase、Hive搭建环境遇到的错误以及解决方法

    大数据学习系列之八----- Hadoop.Spark.HBase.Hive搭建环境遇到的错误以及解决方法 参考文章: (1)大数据学习系列之八----- Hadoop.Spark.HBase.Hiv ...

  6. HIVE学习系列——windows Hadoop安装(上)

    文章目录 整体流程概览 jre环境 jre安装 jre环境变量配置 Hadoop安装与配置 官网下载步骤 清华镜像下载步骤 Hadooponwindows下载 配置系统变量 hadoop初始文件配置 ...

  7. 大数据学习系列之七 ----- Hadoop+Spark+Zookeeper+HBase+Hive集群搭建 图文详解

    引言 在之前的大数据学习系列中,搭建了Hadoop+Spark+HBase+Hive 环境以及一些测试.其实要说的话,我开始学习大数据的时候,搭建的就是集群,并不是单机模式和伪分布式.至于为什么先写单 ...

  8. hadoop 学习路线

    Posted: Sep 6, 2013 Tags: Hadoophadoop familyroadmap Comments: 40 Comments Hadoop家族学习路线图 Hadoop家族系列文 ...

  9. Hadoop学习笔记一 简要介绍

    Hadoop学习笔记一 简要介绍 这里先大致介绍一下Hadoop.     本文大部分内容都是从官网Hadoop上来的.其中有一篇介绍HDFS的pdf文档,里面对Hadoop介绍的比较全面了.我的这一 ...

最新文章

  1. git命令每次都要输入账号密码解决方法
  2. mysql实训报告_mysql数据库技术》实验报告.doc
  3. 英特尔开源版HE-Transformer,对于隐私数据AI终于上手了!
  4. 深度学习相关资料总结
  5. 案例:服务器输出字符数据到浏览器 || 乱码问题|| 案例:服务器输出字节数据到浏览器
  6. stm32 iic接口 进入busy_STM32通过IIC接口读取JY61模块MPU6050陀螺仪芯片数据核心程序...
  7. extjs中js资源缓存策略
  8. [HNOI2008]GT考试
  9. 最新版dotnet-cli下的ASP.NET Core和asp.net mvc【RC2尝鲜】
  10. Leetcode--94. 二叉树的中序遍历(迭代递归)
  11. 《纵向切入ASP.NET 3.5控件和组件开发技术》笔记:高效率事件集合对象
  12. Case 2-1:用空间平滑法分析华南地区的TAI语地名分布
  13. 解决GitHub下载速度慢下载失败的问题
  14. Colorbox 参数设置-中文版
  15. 微信里iphone后退不刷新问题解决方案,真实有效
  16. Excel文件 实用操作小技巧
  17. xp系统设置ntp服务器,xp设置ntp服务器地址
  18. FileZilla使用手册
  19. Bootstrap按钮元素使用方法
  20. 系统应用 odex 转 dex

热门文章

  1. jspwiki mysql_Wiki.js初体验
  2. 电脑技巧:分享七个解决烦人的弹窗广告的小技巧
  3. 12张图带你彻底理解分布式事务产生的场景和解决方案!!
  4. 牛逼的程序员,都长什么样?
  5. 硬件:笔记本常见故障处理技巧与思路,值得收藏!
  6. 【整理】Spring 常用注解!千万不要错过!
  7. 程序员特有的9个坏习惯
  8. MYSQL数据库索引设计的原则
  9. 网络安全用python吗_使用Python进行网络安全渗透——密码攻击测试器
  10. python 栈【测试题】