PageRank 算法
算法原理
PageRank算法是Coogle搜索擎对检索结果的一种排序算法。它的基本思想主要是来自传统文献计量学中的文献引文分析,即一篇文献的质量和重要性可以通过其他文献对其引用的数量和引文质量来衡量,也就是说,一篇文献被其他文献引用越多,并且引用的文献的质量越高,则该文献本身就越重要。
重要假设
- 数量假设:在Web图模型中,如果一个页面节点接收到的其他网页指向的入链数量越多,那么这个页面越重要。
- 质量假设:指向页面A的入链质量不同,质量高的页面会通过链接向其他页面传递更多的权重。所以越是质量高的页面指向页面A,则页面A越重要。
具体实现
PagsRank算法的具体实现可以利用网页所对应图的邻接矩阵来表达超链接关系。为此,首先写出所对应图的邻接矩阵V。为了能将网页的页面等级值平均分配给该网页所链接指向的网页,对W各个行向量进行归一化处理,得到矩阵P。矩阵P称为状态转移概率矩阵,它的各个行向量元素之和为1,PT 的最大特征值(一定为1)所对应的归一化特征向量即为各顶点的PageRank值。
PageRank值的计算步骤如下:
-
构造有向图 D = ( V , A , W ) D=(V,A,W) D=(V,A,W),其中 V = { v 1 , v 2 , . . . , v N } V=\{v_1,v_2,...,v_N\} V={v1,v2,...,vN}为顶点集合,每一个网页是的一个顶点,A为弧的集合,网页间的每一个超链接是图的一条弧,邻接矩阵 W = ( w i j ) N × N W=(w_{ij})_{N\times N} W=(wij)N×N,如果从网页i到网页j有超链接,则 w i j = 1 w_{ij}=1 wij=1,否则为0。
w = np.zeros((6,6)) #邻接矩阵初始化 for i in range(len(L)): w[L[i][0]-1,L[i][1]-1] = 1
-
记矩阵 r i = ∑ j = 1 N w i j {r_i} = \sum\limits_{j = 1}^N {{w_{ij}}} ri=j=1∑Nwij的行和为,它给出了页面i的链出链接数目。定义矩阵 P = ( p i j ) N × N P=(p_{ij})_{N \times N} P=(pij)N×N如下:
p i j = w i j r i p_{ij}=\frac{{{w_{ij}}}}{{{r_i}}} pij=riwijw = np.zeros((6,6)) #邻接矩阵初始化 for i in range(len(L)): w[L[i][0]-1,L[i][1]-1] = 1 r = np.sum(w,axis=1,keepdims=True) P = w / r #这里利用矩阵广播
-
PT 的最大特征值(一定为1)所对应的归一化特征向量即为各顶点的PageRank值。
val, vec= eigs(P.T,1); V=vec.real V=V.flatten(); #展开成(n,)形式的数组 V=V/V.sum(); print("V=",np.round(V,4)) plt.bar(range(1,len(w)+1), V, width=0.6, color='b') plt.show()
例子1
影响力评价问题
图1,给出了6篇文章之间的引用关系,即文章1分别引用了文章2、4、5、6;文章2分别引用了文章4、5、6;等等,试给出6篇文章影响力大小的排序。
#程序文件ex3_3.py
import numpy as np
from scipy.sparse.linalg import eigs
import pylab as plt
import sympy as sp
L = [(1,2),(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,1),(3,2),(3,4),(4,5),(4,6),(5,3),(5,6),(6,3)]
w = np.zeros((6, 6)) # 邻接矩阵初始化
for i in range(len(L)):
w[L[i][0]-1, L[i][1]-1] = 1
r = np.sum(w, axis=1, keepdims=True)
for i in range(len(r)):
if r[i][0] != 0:
r[i][0] = sp.Rational(r[i][0] ** -1)
r = np.array(r)
print(r) # 由于0不为分母,先将r成以-1方,避免相除出错。
P = w * r # 这里利用矩阵广播
print(P)
val, vec = eigs(P.T, 1)
V = vec.real
V = V.flatten() # 展开成(n,)形式的数组
V = V/V.sum()
print("V=", np.round(V, 4))
plt.bar(range(1, len(w)+1), V, width=0.6, color='b')
plt.show()
V= [0.0937 0.1172 0.2813 0.1563 0.1406 0.2109]