PageRank算法原理剖析及Spark实现

1. 什么是PageRank

PageRank对网页排名的算法,曾是Google发家致富的法宝。PageRank算法计算每一个网页的PageRank值,然后根据这个值的大小对网页的重要性进行排序。


2. 简单PageRank算法

首先,将Web做如下抽象:

  • 将每个网页抽象成一个节点
  • 如果一个页面 A 有链接直接链向B,则存在一条有向边从 A B(多个相同链接不重复计算边)。

因此,整个Web被抽象为一张有向图。现在假设世界上只有四张网页: ABCD ,其抽象结构如下图:

简单PageRank计算

显然这个图是强连通的(从任一节点出发都可以到达另外任何一个节点)。然后需要用一种合适的数据结构表示页面间的连接关系。

PageRank算法基本思想描述:被用户访问越多的网页更可能质量越高,而用户在浏览网页时主要通过超链接进行页面跳转,因此需要通过分析超链接组成的拓扑结构来推算每个网页被访问频率的高低。最简单的,我们可以假设当一个用户停留在某页面时,跳转到页面上每个被链页面的概率相同

例如,上图中 A 页面链向BCD,所以一个用户从 A 跳转到BCD的概率各为 1/3 。设一共有N个网页,则可以组织这样一个N维矩阵,其中 i j列的值表示用户从页面 j 转到页面i的概率。这样一个矩阵叫做转移矩阵(Transition Matrix)。下面是上图的转移矩阵 M

M=01/31/31/31/201/2000011/21/200(1)

设初始时每个页面的 rank 值为 1/N ,这里就是 1/4 。按 AD 顺序得到向量 v

v=1/41/41/41/4(2)

注意: M 第一行分别是ABC D 转移到页面A的概率,而 v 的第一列分别是ABC D 当前的rank,因此用 M 的第一行乘以v的第一列,所得结果就是页面A最新 rank 的合理估计,同理, Mv 的结果就分别代表 ABCD rank 值。

Mv=1/45/245/251/4(3)

然后用 M 再乘以这个新的rank向量,又会产生一个 rank 向量。迭代这个过程,可以证明 v 最终会收敛,即vMv,此时计算停止。最终的 v 就是各个页面的pagerank值。上面的向量经过几步迭代后,大约收敛在 1/4,1/4,1/5,1/4 ,这就是 ABCD 最后的 pagerank


3. 终止点问题

上面过程要满足收敛性,需要具备一个条件:图是强连通的,即从任意网页可以到达其他任意网页。

互联网中存在网页不满足强连通的特性,因为有一些网页不指向任何网页,按照上面公式迭代计算下去,导致前面累计得到的转移概率被清零,最终得到的概率分布向量所有元素几乎都为0

假设把上面图中 C D的链接丢掉, C 变成了一个终止点,得到下面这个图:

终止点问题

转移矩阵M为:

M=01/31/31/31/201/2000001/21/200(4)

不断迭代,最终得到所有元素都为0。

v=1/41/41/41/41/45/245/241/127/481/89/481/125/4813/1441/97/1445/7213/2881/97/144...0000(5)


4. 陷阱问题

陷阱问题:是指有些网页不存在指向其他网页的链接,但存在指向自己的链接。比如下面这个图:

陷阱问题

这种情况下,PageRank算法不断迭代会导致概率分布值全部转移到 c 网页上,这使得其他网页的概率分布值为0,从而整个网页排名就失去了意义。如果按照上面图则对应的转移矩阵M为: 

M=01/31/31/31/201/2000101/21/200(6)

不断迭代,最终得到如下结果:

v=1/41/41/41/41/45/2411/241/120010(7)


5. 完整PageRank算法

为了解决终止点问题和陷阱问题,下面需要对算法进行改进。假设选取下一个跳转页面时,既不选当前页面,也不选当前网页上的其他链接,而是以一定概率跳转到其他不相关网页,那么上面两个问题就能得到很好的解决,这就是完整PageRank算法思想

假设跳转到当前页面(包括当前页面上的链接)的概率为 a (也称为基尼系数),那么跳转到其他页面概率为(1a),进一步假设每个页面被访问的概率相同都是 1/n ,于是原来的迭代公式转化为:

v=αMv+(1α)e(8)

假设 α 的值为0.85, e 是网页数目的倒数,共4个网页,所以e等于 1/4 。现在计算有陷阱的网页的概率分布:

v===αMv+(1α)e0.8501/31/31/31/201/2000101/21/2001/41/41/41/4+0.151/41/41/41/40.250.220.430.11(9)

利用上面公式继续迭代下去,直到收敛,得到最终 rank 值。


6. Spark实现RageRank

这里简化初始值为1.0, α/N 设置为0.15,迭代次数参考《数学之美》中提到:“一般来讲,只要10次左右的迭代基本上就收敛了”,这里设置为10次。

    // 生成网页边的关系
    val links = sc.parallelize(Array(('A',Array('D')),('B',Array('A')),
       ('C',Array('A','B')),('D',Array('A','C'))),2).map(x => (x._1, x._2)).cache()

    // 初始化rank值,2表示分两个partition
    var ranks = sc.parallelize(Array(('A',1.0),('B',1.0),('C',1.0),('D',1.0)), 2)

    // 迭代10次
    for ( i <- 1 to 10){
       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)
       ranks = reduceByKeyRDD.mapValues(0.15 + 0.85 * _)

    }

7. 参考


【完】

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值