Scala+Spark:PageRank算法逐行精讲

 

PageRank中的依赖关系

PageRank,网页排名,又称网页级别、Google左侧排名或佩奇排名,是一种根据网页之间相互的超链接计算的技术,而作为网页排名的要素之一,以Google公司创办人拉里·佩奇(Larry Page)之姓来命名。Google用它来体现网页的相关性和重要性,在搜索引擎优化操作中是经常被用来评估网页优化的成效因素之一。Google的创始人拉里·佩奇和谢尔盖·布林于1998年在斯坦福大学发明了这项技术。

PageRank通过网络浩瀚的超链接关系来确定一个页面的等级。Google把从A页面到B页面的链接解释为A页面给B页面投票,Google根据投票来源(甚至来源的来源,即链接到A页面的页面)和投票目标的等级来决定新的等级。简单的说,一个高等级的页面可以使其他低等级页面的等级提升。

PageRank让链接来"投票"

一个页面的“得票数”由所有链向它的页面的重要性来决定,到一个页面的超链接相当于对该页投一票。一个页面的PageRank是由所有链向它的页面(“链入页面”)的重要性经过递归算法得到的。一个有较多链入的页面会有较高的等级,相反如果一个页面没有任何链入页面,那么它没有等级。

我们实现一个如下如所示的网络,箭头表示超链接,节点表示网页。

简单的PageRank算法存在两个重要的数据结构,分别是ranks(每个URL的权重,初始值为1)和links(记录这URL之间的指向的关系),则PageRank算法可以描述如下:

1.将每一个URL的权重都设置为1

2.对于每一次迭代,将每一个URL的权重贡献发送给邻居

3.对于每一个URL,将收到的权重贡献相加成contribs,重新计算ranks=0.15+0.85*contribs

代码如下:

var links = sc.parallelize(Array(('A',Array(‘B','C','D')),('B',Array('A','D')), ('D',Array('B','C'))),2)
var links = links.map(x=>(x._1, x._2)).cache()
var ranks = sc.parallelize(Array(('A',1.0),('B',1.0),('C',1.0).('D',1.0)),2)
for(i <- 1 to ITERATIONS){
    val contribs = links.join(ranks,2)
    val flatMapRDD = contribs.flatMap{case(url,(links,rank))=>links.map(dest=>(dest,rank/links.size))}
    val reduceByKeyRDD = flatMapRDD.reduceByKey(_+_,2)
    val ranks = reduceByKeyRDD.mapValues(0.15+0.85*_)
}

这段代码其实挺复杂的,我们一行一行看:

var links = sc.parallelize(Array(('A',Array(‘B','C','D')),('B',Array('A','D')), ('D',Array('B','C'))),2)

 这一行,就是建立上面给到的网络表示,A和BCD链接,B指向AD。。后面的2是说数据分为两个分区,下面也差不多。

var links = links.map(x=>(x._1, x._2)).cache()

这一行,就是一个映射操作,例如 (Array(('A',Array(‘B','C','D')),就会被映射为(A,B), (A, C), (A, D)。后边的caceh是典型的action操作,把当前数据装载进内存。

var ranks = sc.parallelize(Array(('A',1.0),('B',1.0),('C',1.0).('D',1.0)),2)

这行是给每个节点的权重给一个初始值。

val contribs = links.join(ranks,2)

 这个join操作,会把上面的图和权重结合起来,例如A,就会转化成(A, (B, 1.0)) ,(A, (C, 1.0)) ,(A, (D, 1.0)) 这样的形式。

val flatMapRDD = contribs.flatMap{case(url,(links,rank))=>links.map(dest=>(dest,rank/links.size))}

这一步就是把上一步(A, (B, 1.0))形式的元组用case匹配,然后得到这个超链接的能给目标节点贡献的权重。

val reduceByKeyRDD = flatMapRDD.reduceByKey(_+_,2)

这一步就是把上一步给每个超链接贡献的权重按节点加起来。

val ranks = reduceByKeyRDD.mapValues(0.15+0.85*_)

 这就是按上文讲到的公式更新权重啦。

在PageRank的迭代算法中需要进行一次flatMap操作,以得到flatMapRDD。此RDD已经丢失partitioner函数的信息,所以在进行reduceByKey的过程中仍然有shuffle的过程。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值