目录
- 1 PageRank的定义
- 1.1 基本想法
- 1.2 有向图和随机游走模型
- 1 有向图(directed graph)
- 2 随机游走模型
- 3 PageRank的基本定义
- 4 PageRank的一般定义
- 2 PageRank的计算
- 2.1 迭代算法
- 2.2 幂法(power method)
- 2.3 代数算法
- 总结
PageRank算法是图的链接分析(link analysis)的代表性算法,属于图数据上的无监督学习方法。
PageRank算法最初作为互联网网页重要度的计算方法,1996年由Page和Brin提出,并用于谷歌搜索引擎的网页排序。
其他应用还有:社会影响力分析、文本摘要等。
1 PageRank的定义
1.1 基本想法
PageRank是定义在网页集合上的一个函数,它对每个网页给出一个正实数,表示网页的重要程度。
假设互联网是一个有向图,在其基础上定义随机游走模型,即一阶马尔科夫链,表示网页浏览者在互联网上随机浏览网页的过程。假设浏览者在每个网页依照链接出去的超链接以等概率跳转到下一个网页,并在网上持续不断进行这样的跳转,这个过程形成一阶马尔科夫链。PageRank表示这个马尔科夫链的平稳分布。每个网页的PageRank值就是平稳概率。
两种直观情形:
①一个网页,如果指向该网页的超链接越多,随机跳转到该网页的概率也就越高,该网页的PageRank值就越高,这个网页也就越重要;
②一个网页,如果指向该网页的PageRank值越高,随机跳转到该网页的概率也就越高,该网页的PageRank值就越高,这个网页也就越重要。
PageRank的计算通常是一个迭代过程。先假设一个初始分布,通过迭代,不断计算所有网页的PageRank值,直到收敛为止。
1.2 有向图和随机游走模型
1 有向图(directed graph)
定义 有向图记作,其中V(vertex)和E(edge)分别表示节点和有向边的集合。
强连通图(strongly connected graph): 如果一个有向图从其中任何一个结点出发可以到达其他任何一个结点。
周期性结点: 假设k是一个大于1的自然数,如果从有向图的一个结点出发返回到这个结点的路径长度都是k个倍数,那么称这个结点为周期性结点。
非周期性图(aperiodic graph): 一个有向图不含有周期性结点。否则为周期性图。
2 随机游走模型
定义 给定一个含有n个结点的有向图,在有向图上定义random walk模型,其中结点表示状态,有向边表示状态之间的转移,假设从一个结点到通过有向边相连的所有结点的转移概率相等。具体地,转移矩阵(stochastic matrix)是一个n阶矩阵,取值规则为:如果结点有个有向边连出,并且结点是其连出的一个结点,则;否则。
转移矩阵具有如下简单性质:
①;
②。
随机游走在某个时刻t访问各个结点的概率分布就是马尔科夫链在时刻t的状态分布,用一个行向量表示,那么在时刻t+1访问各个结点的概率分布为满足。
3 PageRank的基本定义
定义 给定一个包含n个结点的强连通且非周期性的有向图,在有向图上定义随机游走模型。这个马尔科夫链具有平稳分布,平稳分布R称为这个有向图的PageRank。R的各个分量称为各个结点的PageRank值。
显然有:
①;
②;
③;
这里表示指向结点的结点集合,表示结点连出的有向边的个数。
因为是非周期的,所以是无环图,所以,所以
,所以
。
定理 强连通且非周期的有限状态马尔科夫链,有唯一平稳分布存在,并且当时间趋于无穷时状态分布收敛于唯一的平稳分布。
1/3
1/3
1/3
1/2
1/2
1
1/2
1/2
A
B
C
D
例1 求上面有向图的PageRank。(原图不会画…)
import numpy as np
M = np.array([[0, 1/3, 1/3, 1/3],
[1/2, 0, 0, 1/2],
[1, 0, 0, 0],
[0, 1/2, 1/2, 0]])
R = np.array([1/4, 1/4, 1/4, 1/4])
for i in range(30):
R = np.matmul(R, M)
print(R)
[0.33333333 0.22222222 0.22222222 0.22222222]
4 PageRank的一般定义
一般的有向图未必满足强连通且非周期性的条件。比如,在互联网,大部分网页没有链接出去的超链接,也就是说从这些网页无法跳转到其他网页,所以PageRank的基本定义不适用。
1/3
1/3
1/3
1/2
1/2
1/2
1/2
A
B
C
D
import numpy as np
M = np.array([[0, 1/3, 1/3, 1/3],
[1/2, 0, 0, 1/2],
[0, 0, 0, 0],
[0, 1/2, 1/2, 0]])
R = np.array([1/4, 1/4, 1/4, 1/4])
for i in range(10):
R = np.matmul(R, M)
print(R)
[0.00803454 0.01170971 0.01170971 0.01170971]
可以理解为概率被结点C吸收了。
PageRank一般定义的想法是在基本定义的基础上导入平滑项。
模型1:随机游走模型,根据有向图得到的基本转移矩阵M,未必具有平稳分布;
模型2:完全随机游走模型,其转移矩阵的元素全部为1/n。
两者做线性组合构成一个新的转移矩阵,在其上定义一个新的马尔科夫链,则该马尔科夫链一定具有平稳分布,且平稳分布满足,是系数,称为阻尼因子(damping factor),则R表示的就是有向图的一般PageRank。
则每个结点的PageRank为,所有结点的PageRank值都不会为0。
第二个机制保证从没有连接出去的超链接的网页也可以跳转出。从而可以保证平稳分布,即存在一般PageRank,因而一般PageRank适用于任何结构的网络。
2 PageRank的计算
2.1 迭代算法
给定一个含有n个结点的有向图,转移矩阵为M,有向图的一般PageRank由迭代公式的极限向量确定。
例2 令,求图的PageRank。
1/3
1/3
1/3
1/2
1/2
1/2
1/2
1
A
B
C
D
迭代算法
import numpy as np
def IterationMethod(M, d):
n = M.shape[0]
E = np.ones((n, n))
E = (1-d)*1/n*E
M = d*M+E
R = np.ones((1,n))/n
for i in range(50):
R = np.matmul(R, M)
print(R)
M = np.array([[0, 1/3, 1/3, 1/3],
[1/2, 0, 0, 1/2],
[0, 0, 1, 0],
[0, 1/2, 1/2, 0]])
IterationMethod(M, 0.8)
[[0.10135135 0.12837838 0.64189189 0.12837838]]
计算结果表明,结点C的PageRank值超过一半。
2.2 幂法(power method)
幂法是一个常用的PageRank计算方法,通过近似计算矩阵的主特征值(dominant eigenvalue)和主特征向量(dominant eigenvector)求得有向图的一般PageRank。主特征值是指绝对值最大的特征值,主特征向量是其对应的特征向量,方向定,不唯一。
假设要求n阶矩阵A的主特征值和主特征向量,采用下面的步骤:
①任取一个初始n维向量,构造如下的一个n维向量序列
②假设矩阵A有n个特征值,按照绝对值大小排列
对应的n个线性的特征向量为,这n个特征向量构成n维空间的一组基。
③将初始向量表示为的线性组合
④假设矩阵A的主特征值是特征方程的单根,由上式得
⑤则
在实际计算时,为了避免出现绝对值过大或过小的情况,通常在每步迭代后就进行规范化,将向量除以其范数,即
这里的范数为
转移矩阵为
Perron-Frobenius定理 一般PageRank的向量R是矩阵A的主特征向量,主特征值是1。(所以)
例3 取,求图的一般PageRank。
A
B
C
幂法
import numpy as np
def PowerMethod(M, d):
E = np.ones((M.shape[0], M.shape[0]))
A = d*M+(1-d)/M.shape[0]*E
x = np.ones((1, M.shape[0]))
z = x+1
while np.linalg.norm(x-z)!=0:
z = x
y = np.matmul(x, A)
x = y/np.linalg.norm(y, ord=np.inf)
print(x)
M1 = np.array([[0, 1/2, 1/2],
[0, 0, 1],
[1, 0, 0]])
M2 = np.array([[0, 1/3, 1/3, 1/3],
[1/2, 0, 0, 1/2],
[0, 0, 1, 0],
[0, 1/2, 1/2, 0]])
PowerMethod(M1, 0.85)
[[0.38778971 0.21481063 0.39739966]]
PowerMethod(M2, 0.8)
[[0.10135135 0.12837838 0.64189189 0.12837838]]
2.3 代数算法
代数算法通过一般转移矩阵的逆矩阵计算求得有向图的一般PageRank。
写成,
则,。
当时,线性方程组的解存在且唯一。
代数算法
import numpy as np
def AlgebraPageRank(M, d):
E = np.ones((1, M.shape[0]))
I = np.eye(M.shape[0])
E = (1-d)*(1/M.shape[0]) * E
M = np.linalg.inv(I-d*M)
print(np.matmul(E, M))
M1 = np.array([[0, 1/2, 1/2],
[0, 0, 1],
[1, 0, 0]])
M2 = np.array([[0, 1/3, 1/3, 1/3],
[1/2, 0, 0, 1/2],
[0, 0, 1, 0],
[0, 1/2, 1/2, 0]])
AlgebraPageRank(M1, 0.85)
[[0.38778971 0.21481063 0.39739966]]
AlgebraPageRank(M2, 0.8)
[[0.10135135 0.12837838 0.64189189 0.12837838]]