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