3. PageRank
PageRank:网页级别,Google专利技术。是Google用于标识网页的等级和重要性的一种方法。
源程序来自github,后文有链接
运行环境:
- CentOS-7.6-Minimal * 3 由Vmware平台搭建
三台主机对应IP地址:192.168.239.100 hadoop100
192.168.239.101 hadoop101
192.168.239.102 hadoop102
环境:hadoop-2.7.7 + JDK-8-251
- 三台虚拟机上节点分配:
hadoop100:DataNode NameNode NodeManager
hadoop200: ResourceManager NodeManager DataNode
hadoop300:NodeManager DataNode JobHistoryServer
- 程序的开发验证由PC机实现
Intellij IDEA 2018.4 + hadoop-2.7.7 + JDK-8-251 + Maven-3.3.9
3.1 算法思想
-
PageRank是一种由搜索引擎根据网页之间相互的超链接计算的技术,而作为网页排名的要素之一。Google用它来体现网页的相关性和重要性,在搜索引擎优化操作中是经常被用来评估网页优化的成效因素之一。
-
PageRank用于衡量特定网页相对于搜索引擎索引中的其他网页而言的重要程度。
-
PageRank实现了将链接价值概念作为排名因素。PageRank让链接来”投票”
-
一个页面的“得票数”由所有链向它的页面的重要性来决定,到一个页面的超链接相当于对该页投一票。一个页面的PageRank是由所有链向它的页面(“链入页面”)的重要性经过递归算法得到的。一个有较多链入的页面会有较高的等级,相反如果一个页面没有任何链入页面,那么它没有等级。
-
简单一句话概括:从许多优质的网页链接过来的网页,必定还是优质网页。
-
PageRank的计算基于以下两个基本假设:
- 数量假设:如果一个页面节点接收到的其他网页指向的入链数量越多,那么这个页面越重要
- 质量假设:指向页面A的入链质量不同,质量高的页面会通过链接向其他页面传递更多的权重。所以越是质量高的页面指向页面A,则页面A越重要。
-
计算公式:
- 公式一:
PR(A):某个网页的PR值
d:阻尼系数,含义是在任意时刻,用户到达某页面后并继续向后浏览的概率
PR(Ti):链出网页Ti的PR值
C(Ti):网页Ti存在的链接的数量
m:源网页包含链接的数量
- 公式二:
N:总的网页数量
参考:浅入浅出:PageRank算法
3.2 算法流程
-
下载元数据集:测试数据集获取,注意数据集最好是以‘\t’分隔的,不然需要修改代码
数据基本格式:<nodeA> <nodeB>
which denotes an edge going from <nodeA> to <nodeB> and is seprated by tab。 -
Mapreduce_1
map1输入:<nodeA> <nodeB> 输出:<nodeA> <nodeB>
reduce1输入:<title> <link1>,<link2>,<link3>,<link4>,...,<linkN>
输出:<title> <page-rank> <link1>,<link2>,<link3>,<link4>,...,<linkN>
输出添加了<pagerank>这里把pagerank初始化为:d/N 阻尼系数/总结点数
- Mapreduce_2 (默认这个Mapreduce需要迭代两次)
map2输入: <title> <page-rank> <link1>,<link2>,<link3>,<link4>,... ,<linkN>
输出: <title> |<link1>,<link2>,<link3>,<link4>, ... , <linkN> 输出格式1
‘|’的目的是让reduce_2区别处理两个输入
<link> <page-rank> <total-links> 输出格式2
输出格式2的目的是计算求和公式那里。
根据公式,每一个从当前页面链出的网页必然都会用到当前页面的
<page-rank> 和<total-links>,这为求和公式打好基础
reduce2输入:<title> |<link1>,<link2>,<link3>,<link4>, ... , <linkN> 输入格式1
<link> <<page-rank> <total-links>>(迭代器) 输入格式2
输出:<title> <page-rank> <link1>,<link2>,<link3>,<link4>,... ,<linkN>
- Mapreduce_3
map3输入:<title> <page-rank> <link1>,<link2>,<link3>,<link4>,... ,<linkN>
输出:<page-rank> <title>
这里不会再有reduce,因为通过map阶段的sort即可完成对结果的排序输出
3.3 在Hadoop分布式集群中运行PageRank
-
数据集准备:CA-AstroPh.txt
-
上传到HDFS
# 创建输入输出文件夹 $ hadoop fs -mkdir /pagerank/input #输入 $ hadoop fs -mkdir /pagerank/output #输出 # 上传 $ hadoop fs -put /home/hadoop1/data/input/CA-AstroPh.txt /pagerank/input
-
将IDEA工程打包,命名:Pagerank_3-pagerank.jar
-
运行程序
$ hadoop jar Pagerank_3-pagerank.jar cn/hadoop/pagerank.PageRank --input /pagerank/input --output pagerank/output # 总计有4个参数,想要跑起来,只要给出输入和输出路径即可
-
查看输出
$ hadoop fs -cat /pagerank/output/result/part-r-00000 # 这里结果中出现了 Infinity 100626 Infinity 100625 Infinity 100624 Infinity 100622 Infinity 100621 # 这肯定不是我们想要的结果,需要进行调试,定位原因为没有计算出PR的初始值, # 初始值被赋为无穷,说明除数为零了,但是程序没有报错,修正分母就没有问题了。 # 直接对分母进行赋值即可 # 结果 0.15030437707901 118342 0.15035437047481537 4501 0.15035437047481537 8745 0.15035437047481537 51101 0.15035437047481537 725 0.15035437047481537 2167
//原因分析:分母的值是从驱动类中获取的,但是获取的值始终是零,修改了一下, //单机调试的情况下是不会发生错误的,但是在分布式集群中调试就会发生错误, //索性直接修改分母为数据集节点总 # 数,那么就正常了。 String links = ( PageRank.DAMPING / PageRank.NODES.size()) + "\t"; String links = (PageRank.DAMPING / 18772) + "\t"; //这里直接对分母进行赋值
-
查看运行时间 总计运行1‘42" 数据量大小:5M (5161KB) 台式机用不上10s