PageRank网页价值算法

一.简介

  PageRank是Google提出的算法,用于衡量特定网页相对于其它网页而言的重要程度。是Google创始人拉里.佩奇和谢尔盖.布林于1997年创造的,用于实现将链接价值概念作为排名的重要因素。

二.算法原理

  1.入链

    PageRank让链接来投票,到一个页面的超链接相当于对该网页投一票。

  2.入链个数

    如果一个页面节点接收到的其它网页指向的入链数量越多,那么这个页面就越重要。

  3.入链质量

    指向页面A的不同入链质量不同,质量高的页面会通过链接向其它页面传递更大的权重。所有越是质量高的页面指向页面A,则页面A就越重要。

  4..图解

    

    1.站在A的角度:需要将自己的PR值分给B,D。

    2.站在B的角度:收到来自A,C,D的PR值。

    3.PR值需要迭代计算,且其PR值会逐渐趋于稳定。

  5.初始值

    1.Google的每个页面设置相同的PR值,PageRank算法类似,每个页面的PR初始值为1。

    2.迭代计算,Google不断的重复计算每个页面的PageRank,经过不断的迭代计算,这些页面的PR值会趋于稳定,这就是收敛的状态。

  6.收敛标准

    1.每个页面的PR值和上一次计算的PR值相等。

    2.设定一个差值指标【例如:0.001】,当所有页面上一次计算的PR值差值平均小于该标准时,则认为其已经收敛。

    3.设定一个百分比【例如:99%】,当99%的页面和上一次计算的PR值相等时认为其已收敛。

    

三.修正PageRank

  1.站在互联网的角度看,只有出度而没有入度,PR值会趋向于0,只有入度而没有出度,PR值会趋向于很大。

  2.修正PageRank计算公式,增加阻尼系数,一般取值为d=0.85。

  3.完整PageRank计算公式:

    

    备注:

      d:阻尼系数

      M(i):指向i的页面集合

      L(i):页面的出链数

      PR(Pj):j页面的PR值

      n:所有页面数

四.代码实现

 1 package big.data.analyse.pageRank
 2 
 3 import org.apache.log4j.{Level, Logger}
 4 import org.apache.spark.sql.SparkSession
 5 object PageRunJob {
 6   def main(args: Array[String]): Unit = {
 7     /**
 8       * 设置日志级别
 9       */
10     Logger.getLogger("org").setLevel(Level.WARN)
11     val spark = SparkSession.builder//创建spark入口
12     .master("local[2]")//设置本地运行模式
13     .appName("pageRank")
14     .config("spark.sql.warehouse.dir","file:///D://warehouse")//设置本地仓库
15     .getOrCreate()
16     //读取关系矩阵
17     val firstInputPath = spark.read.textFile("src/big/data/analyse/pageRank/pagerank.txt")
18     // 求出n
19     val n = firstInputPath.count()
20     //获取所有节点
21     val onlyKey = firstInputPath.rdd.map(line => line.split(",")(0))
22     onlyKey.cache()//缓存(方便重用,后面多次使用时建议使用)
23     //获取所有映射关系
24     val kvMap = firstInputPath.rdd.map(line =>
25     {
26         val array = line.split(",").array
27         (array(0),array(1))
28     })
29     kvMap.cache()//缓存(方便重用)
30 
31     val bk = onlyKey.map(k=>(k,1)).reduceByKey(_+_)
32 
33     val d = 0.85 // 阻尼系数
34     //延迟加载
35     val first = onlyKey.map(k=>(k,1.0)) // 默认每个网页初始价值为1
36         .reduceByKey(_+_) // 求每个网页出度
37         .map(line =>(line._1,((1-d)/n) + d * 1/line._2)) // 出度越大,价值越小
38         .sortByKey()//排序
39 
40     first.cache()//缓存(方便重用)
41     println("<<<<<<<<<<<<<<<<<<<正在进行第1迭代计算,当前误差为:"+first.count()+">>>>>>>>>>>>>>>>>>>")
42     first.foreach(println)
43 
44     val frist_bk = first.join(bk)
45       .map(row => (row._1,row._2._1/row._2._2)) // 重新平衡每个网页的出度价值
46 
47     var second = kvMap.join(frist_bk)
48       .map(row => row._2)
49       .reduceByKey(_+_)
50       .sortByKey()//排序
51 
52     /**
53       * 统计初次误差
54       */
55     val subValue = second.join(first).map(k=>k._2).sortByKey()
56       .map(line =>(line._2-line._1).abs).sum()
57     println("<<<<<<<<<<<<<<<<<<<正在进行第2迭代计算,当前误差为:"+subValue+">>>>>>>>>>>>>>>>>>>")
58     second.foreach(println) // 二次计算每个网页的价值
59 
60     val precision = 0.001//设置精确度
61     var i = 3
62     while(true){
63       val mid_bk = second.join(bk)
64         .map(row => (row._1,((1-d)/n) + d * row._2._1/row._2._2)) // 重新平衡每个网页的出度价值
65 
66       val second_mid = kvMap.join(mid_bk)
67         .map(row => row._2)
68         .reduceByKey(_+_)
69         .sortByKey()//排序
70 
71       val subValue = second_mid.join(second).map(k=>k._2).sortByKey()//计算当前迭代的各节点的价值
72         .map(line =>(line._2-line._1).abs).sum()
73 
74       println("<<<<<<<<<<<<<<<<<<<正在进行第"+i+"迭代计算,当前误差为:"+subValue+">>>>>>>>>>>>>>>>>>>")
75       second_mid.foreach(println) // 二次计算每个网页的价值
76       if(subValue<=precision){
77         println("<<<<<<<<<<<<<<<<<<<当前误差为:"+subValue+"已小于"+precision+",迭代完成!>>>>>>>>>>>>>>>>>>>")
78          return
79       }else{
80         second = second_mid
81          i += 1
82       }
83     }
84     spark.stop()//关闭
85   }
86 }

五.测试数据

百度,博客园
百度,Apache
博客园,GitHub
GitHub,百度
GitHub,博客园
GitHub,Apache
Apache,博客园
Apache,GitHub
Apache,百度
Apache,Apache

六.结果

<<<<<<<<<<<<<<<<<<<正在进行第1迭代计算,当前误差为:4>>>>>>>>>>>>>>>>>>>
(Apache,0.2275)
(GitHub,0.29833333333333334)
(博客园,0.865)
(百度,0.44)
<<<<<<<<<<<<<<<<<<<正在进行第2迭代计算,当前误差为:1.544722222222222>>>>>>>>>>>>>>>>>>>
(Apache,0.37631944444444443)
(GitHub,0.921875)
(博客园,0.37631944444444443)
(百度,0.15631944444444446)
<<<<<<<<<<<<<<<<<<<正在进行第3迭代计算,当前误差为:0.8594461805555556>>>>>>>>>>>>>>>>>>>
(Apache,0.4526015625)
(GitHub,0.42983940972222223)
(博客园,0.4526015625)
(百度,0.3711657986111111)
<<<<<<<<<<<<<<<<<<<正在进行第4迭代计算,当前误差为:0.26803075086805556>>>>>>>>>>>>>>>>>>>
(Apache,0.42071112919560183)
(GitHub,0.51088916015625)
(博客园,0.42071112919560183)
(百度,0.2479656647858796)
<<<<<<<<<<<<<<<<<<<正在进行第5迭代计算,当前误差为:0.1224163202582465>>>>>>>>>>>>>>>>>>>
(Apache,0.3845384511990017)
(GitHub,0.47700557477032696)
(博客园,0.3845384511990017)
(百度,0.26415304366500286)
<<<<<<<<<<<<<<<<<<<正在进行第6迭代计算,当前误差为:0.07653532812499986>>>>>>>>>>>>>>>>>>>
(Apache,0.3741310439556734)
(GitHub,0.43857210439893934)
(博客园,0.3741310439556734)
(百度,0.24686600039804718)
<<<<<<<<<<<<<<<<<<<正在进行第7迭代计算,当前误差为:0.06505502890625>>>>>>>>>>>>>>>>>>>
(Apache,0.3536829932561168)
(GitHub,0.427514234202903)
(博客园,0.3536829932561168)
(百度,0.23376494308694676)
<<<<<<<<<<<<<<<<<<<正在进行第8迭代计算,当前误差为:0.05529677457031257>>>>>>>>>>>>>>>>>>>
(Apache,0.34063676990303304)
(GitHub,0.40578818033462405)
(博客园,0.34063676990303304)
(百度,0.22628666909108067)
<<<<<<<<<<<<<<<<<<<正在进行第9迭代计算,当前误差为:0.04700225838476582>>>>>>>>>>>>>>>>>>>
(Apache,0.32853046572958056)
(GitHub,0.39192656802197257)
(博客园,0.32853046572958056)
(百度,0.2173586313658713)
<<<<<<<<<<<<<<<<<<<正在进行第10迭代计算,当前误差为:0.0399519196270508>>>>>>>>>>>>>>>>>>>
(Apache,0.31823600323759005)
(GitHub,0.37906361983767933)
(博客园,0.31823600323759005)
(百度,0.21085858490709475)
<<<<<<<<<<<<<<<<<<<正在进行第11迭代计算,当前误差为:0.03395913168299314>>>>>>>>>>>>>>>>>>>
(Apache,0.3096414082275123)
(GitHub,0.3681257534399394)
(博客园,0.3096414082275123)
(百度,0.20502650964199703)
<<<<<<<<<<<<<<<<<<<正在进行第12迭代计算,当前误差为:0.028865261930544117>>>>>>>>>>>>>>>>>>>
(Apache,0.30223736265417794)
(GitHub,0.35899399624173184)
(博客园,0.30223736265417794)
(百度,0.2001010960563292)
<<<<<<<<<<<<<<<<<<<正在进行第13迭代计算,当前误差为:0.024535472640962563>>>>>>>>>>>>>>>>>>>
(Apache,0.29598337098977673)
(GitHub,0.3511271978200641)
(博客园,0.29598337098977673)
(百度,0.19594040516583683)
<<<<<<<<<<<<<<<<<<<正在进行第14迭代计算,当前误差为:0.020855151744818112>>>>>>>>>>>>>>>>>>>
(Apache,0.2906571779131597)
(GitHub,0.3444823316766378)
(博客园,0.2906571779131597)
(百度,0.19238250571767906)
<<<<<<<<<<<<<<<<<<<正在进行第15迭代计算,当前误差为:0.017726878983095412>>>>>>>>>>>>>>>>>>>
(Apache,0.28613054254494075)
(GitHub,0.3388232515327322)
(博客园,0.28613054254494075)
(百度,0.18936797761492716)
<<<<<<<<<<<<<<<<<<<正在进行第16迭代计算,当前误差为:0.015067847135631168>>>>>>>>>>>>>>>>>>>
(Apache,0.2822840520447514)
(GitHub,0.33401370145399956)
(博客园,0.2822840520447514)
(百度,0.18680266155840736)
<<<<<<<<<<<<<<<<<<<正在进行第17迭代计算,当前误差为:0.012807670065286408>>>>>>>>>>>>>>>>>>>
(Apache,0.27901370763379935)
(GitHub,0.32992680529754836)
(博客园,0.27901370763379935)
(百度,0.1846225764714762)
<<<<<<<<<<<<<<<<<<<正在进行第18迭代计算,当前误差为:0.010886519555493496>>>>>>>>>>>>>>>>>>>
(Apache,0.2762342693735318)
(GitHub,0.3264520643609118)
(博客园,0.2762342693735318)
(百度,0.1827696743731544)
<<<<<<<<<<<<<<<<<<<正在进行第19迭代计算,当前误差为:0.009253541622169403>>>>>>>>>>>>>>>>>>>
(Apache,0.27387164541939113)
(GitHub,0.32349891120937757)
(博客园,0.27387164541939113)
(百度,0.18119453381080053)
<<<<<<<<<<<<<<<<<<<正在进行第20迭代计算,当前误差为:0.007865510378844143>>>>>>>>>>>>>>>>>>>
(Apache,0.2718634263638678)
(GitHub,0.32098862325810307)
(博客园,0.2718634263638678)
(百度,0.17985574949427757)
<<<<<<<<<<<<<<<<<<<正在进行第21迭代计算,当前误差为:0.0066856838220175074>>>>>>>>>>>>>>>>>>>
(Apache,0.2701564482271857)
(GitHub,0.31885489051160953)
(博客园,0.2701564482271857)
(百度,0.17871775469211776)
<<<<<<<<<<<<<<<<<<<正在进行第22迭代计算,当前误差为:0.005682831248714881>>>>>>>>>>>>>>>>>>>
(Apache,0.26870550997071635)
(GitHub,0.3170412262413848)
(博客园,0.26870550997071635)
(百度,0.17775046422656632)
<<<<<<<<<<<<<<<<<<<正在进行第23迭代计算,当前误差为:0.004830406561407652>>>>>>>>>>>>>>>>>>>
(Apache,0.2674722156001269)
(GitHub,0.31549960434388613)
(博客园,0.2674722156001269)
(百度,0.17692826830383623)
<<<<<<<<<<<<<<<<<<<正在进行第24迭代计算,当前误差为:0.004105845577196454>>>>>>>>>>>>>>>>>>>
(Apache,0.2664239144082584)
(GitHub,0.31418922907513486)
(博客园,0.2664239144082584)
(百度,0.17622940037912804)
<<<<<<<<<<<<<<<<<<<正在进行第25迭代计算,当前误差为:0.0034899687406169944>>>>>>>>>>>>>>>>>>>
(Apache,0.2655328585441725)
(GitHub,0.31307540905877457)
(博客园,0.2655328585441725)
(百度,0.1756353633830431)
<<<<<<<<<<<<<<<<<<<正在进行第26迭代计算,当前误差为:0.002966473429524441>>>>>>>>>>>>>>>>>>>
(Apache,0.26477546111174943)
(GitHub,0.3121286622031833)
(博客园,0.26477546111174943)
(百度,0.17513043167395612)
<<<<<<<<<<<<<<<<<<<正在进行第27迭代计算,当前误差为:0.002521502415095772>>>>>>>>>>>>>>>>>>>
(Apache,0.26413167323858)
(GitHub,0.3113239274312338)
(博客园,0.26413167323858)
(百度,0.1747012397771487)
<<<<<<<<<<<<<<<<<<<正在进行第28迭代计算,当前误差为:0.0021432770528314327>>>>>>>>>>>>>>>>>>>
(Apache,0.2635844535740027)
(GitHub,0.31063990281599124)
(博客园,0.2635844535740027)
(百度,0.1743364266687145)
<<<<<<<<<<<<<<<<<<<正在进行第29迭代计算,当前误差为:0.0018217854949066081>>>>>>>>>>>>>>>>>>>
(Apache,0.26311931684987677)
(GitHub,0.31005848192237784)
(博客园,0.26311931684987677)
(百度,0.1740263355156731)
<<<<<<<<<<<<<<<<<<<正在进行第30迭代计算,当前误差为:0.0015485176706707127>>>>>>>>>>>>>>>>>>>
(Apache,0.26272395063610027)
(GitHub,0.30956427415299403)
(博客园,0.26272395063610027)
(百度,0.1737627580419392)
<<<<<<<<<<<<<<<<<<<正在进行第31迭代计算,当前误差为:0.001316240020070053>>>>>>>>>>>>>>>>>>>
(Apache,0.2623878893546771)
(GitHub,0.30914419755085654)
(博客园,0.2623878893546771)
(百度,0.17353871718685296)
<<<<<<<<<<<<<<<<<<<正在进行第32迭代计算,当前误差为:0.001118804017059577>>>>>>>>>>>>>>>>>>>
(Apache,0.2621022372650241)
(GitHub,0.3087871324393444)
(博客园,0.2621022372650241)
(百度,0.17334828246061157)
<<<<<<<<<<<<<<<<<<<正在进行第33迭代计算,当前误差为:9.509834145005613E-4>>>>>>>>>>>>>>>>>>>
(Apache,0.26185943298905845)
(GitHub,0.3084836270940881)
(博客园,0.26185943298905845)
(百度,0.17318641294329856)
<<<<<<<<<<<<<<<<<<<当前误差为:9.509834145005613E-4已小于0.001,迭代完成!>>>>>>>>>>>>>>>>>>>

Process finished with exit code 0

posted @ 2019-05-24 20:14  云山之巅  阅读(794)  评论(0编辑  收藏  举报