PageRank算法及python代码

目录

1、核心思想

2、基本概念

3、模拟PageRank算法的运行过程​

4、简单PageRank算法

5、终止点问题

6、陷阱问题

7、代码(python)

简单代码:


 

PageRankGoogle算法的重要内容。

20019月被授予美国专利,专利人是Google创始人之一拉里·佩奇(Larry Page)。因此,PageRank里的page不是指网页,而是指佩奇,即这个等级方法是以佩奇来命名的。
   GooglePageRank根据网站的外部链接和内部链接的数量和质量俩衡量网站的价值。PageRank背后的概念是,每个到页面的链接都是对该页面的一次投票, 被链接的越多,就意味着被其他网站投票越多。这个就是所谓的“链接流行度”——衡量多少人愿意将他们的网站和你的网站挂钩。PageRank这个概念引自 学术中一篇论文的被引述的频度——即被别人引述的次数越多,一般判断这篇论文的权威性就越高。

1、核心思想

    PageRank算法以前就是Google的屠龙刀,倚天剑,降龙十八掌。Google显示符合用户搜索的网页的依次显示呢?在以前Google及用过PageRank算法,对每个目标网页进行附上权值,权值大的就靠前显示,权值小的就靠后显示。对,PageRank算法就是给每个网页附加权值的~。PageRank算法借鉴学术界论文重要性的评估方法:谁被引用的次数多,谁就越重要。

注:PageRank算法不单单是按照“被索引数”来给网页付权值的,用PR值表示每个网页被PageRank算法附加的权值

谷歌的两位创始人,当时还是美国斯坦福大学 (Stanford University) 研究生的佩奇 (Larry Page) 和布林 (Sergey Brin) 开始了对网页排序问题的研究。他们的借鉴了学术界评判学术论文重要性的通用方法, 那就是看论文的引用次数。由此想到网页的重要性也可以根据这种方法来评价

于是PageRank的核心思想就诞生了,非常简单

如果一个网页被很多其他网页链接到的话说明这个网页比较重要,也就是PageRank值会相对较

如果一个PageRank值很高的网页链接到一个其他的网页,那么被链接到的网页的PageRank值会相应地因此而提高

2、基本概念

先了解几个基本概念,一遍后面内容理解

1)出链

如果在网页A中附加了网页B的超链接B-Link,用户浏览网页A时可以点击B-Link然后进入网页B。上面这种A附有B-Link这种情况表示A出链B。可知,网页A也可以出链C,如果A中也附件了网页C的超链接C-Link

2)入链

上面通过点击网页A中B-Link进入B,表示由A入链B。如果用户自己在浏览器输入栏输入网页B的URL,然后进入B,表示用户通过输入URL入链B

3)无出链

如果网页A中没有附加其他网页的超链接,则表示A无出链

4)只对自己出链

如果网页A中没有附件其他网页的超链接,而只有他自己的超链接A-Link,则表示A只对自己出链

5)PR

个网页的PR值,概率上理解就是此网页被访问的概率,PR值越高其排名越高

 

3、模拟PageRank算法的运行过程​

详细讲述这个算法之前,不妨让我们用一个游戏,先来简单模拟一下PageRank算法的运行过程,以便读者更好地理解。​

兄弟分30颗豌豆,起初每人10颗,他们每次都要把手里的豌豆全部平均分给自己喜欢的人,下图表示了三兄弟各自拥有的初始豌豆数量,以及相互喜欢的关系(箭头方向表示喜欢,例如老二喜欢老大,老大喜欢老二和老三)

 

经过第一配后,我们可以得到第一次的分配结果:

就这样,让游戏一直进行下去,直到他们手中的豌豆数不再变化为止

​ 那么这个游戏到底是否可以结束呢,如果可以,最终的结果又是什么样的

​ 在此我们用电脑模拟了这个过程,得出的结果是:老大和老二的盘子里各有12颗豌豆,而老三的盘子里有6颗豌豆,这时候无论游戏怎么进行下去,盘子里的豌豆数量都不会再变化

​ 看到这里,读者可能会问:这个游戏和网页排序有什么关系

​ 实际上,PageRank会给每个网页一个数值,这个数值越高,就说明这个网页越“重要”

​ 而刚刚的游戏中,如果把豌豆的数量看作这个数值(可以不是整数),把孩子们看作网页,那么游戏的过程就是PageRank的算法,而游戏结束时豌豆的分配,就是网页的PageRank值

4、简单PageRank算法

首先,将Web做如下抽象

每个网页抽象成一个节点

如果一个页面A有链接直接链向B,则存在一条有向边从A到B(多个相同链接不重复计算边)

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

我们可以看到这个图是强连通的(从任一节点出发都可以到达另外任何一个节点)

然后需要用一种合适的数据结构表示页面间的连接关系

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

对任意一个网页P

I(P) : 表述其重要性,并称之为网页的网页排序,即排序的分值

上图中,网页APR值计算公式为:

我们可以看到只有B、C是可以链接到A的

B同时可以到A和C,所以B到A的分值是PR(B)/2

C只有到A的链接,所以C到A的分值是PR(C)/1

这或许会让你想起 “先有鸡还是先有蛋” 的问题:为了确定一个网页的重要性,我们首先得得知所有指向它的其它网页的重要性。然而,我们可以将这个问题改写成一个更数学化的问题。

首先,建立一个矩阵,称为超链矩阵 (hyperlink matrix,M=[Mij] ,其中第 i 行第j 列的元素为: 

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

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

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

然后用M再乘以这个新的rank向量,又会产生一个rank向量。迭代这个过程,可以证明v最终会收敛,即v≈Mv,此时计算停止。最终的v就是各个页面的pagerank值。上面的向量经过几步迭代后,大约收敛在(0.265, 0.235, 0.206, 0.294),这就是A、B、C、D最后的pagerank。

5、终止点问题

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

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

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

转移矩阵M为:

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

6、陷阱问题

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

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

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

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

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

v′=αMv+(1−α)e

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

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

7、代码(python)

简单代码:

基于

import numpy as np
M = [[0, 1/2,0, 1/2],
     [1/3, 0, 0,1/2],
     [1/3, 1/2, 1,0],
     [1/3,0,0,0]]
U = [1 / 4, 1 / 4, 1 / 4,1/4]
U0 = np.array(U)

U_past_none_alpha = []
while True:
    U = np.dot(M, U)
    # print('Un: ', U)
    if str(U) == str(U_past_none_alpha):
        break
    U_past_none_alpha = U
print('Un converge1 to: ', U)

U_past_has_alpha = []
while True:
    U = 0.8 * (np.dot(M, U)) + 0.2 * U0
    # print('Un: ', U)
    if str(U) == str(U_past_has_alpha):
        break
    U_past_has_alpha = U
print('Un converge2 to: ', U)

猜你喜欢

转载自blog.csdn.net/Andy_shenzl/article/details/83145471