一.算法简介
1.pagerank是Google排名运算法则(排名公式)的一部分,是Google用于用来标识网页的等级/重要性的一种方法,是Google用来衡量一个网站的好坏的唯一标准
2.如果一个网页被很多其他网页链接到的话说明这个网页比较重要,也就是PageRank值会相对较高
##3.如果一个PageRank值很高的网页链接到一个其他的网页,那么被链接到的网页PageRank值也会相应提高。
每个球代表一个网页;球的大小反应了网页的pagerank值的大小.
指向网页B和网页E的链接很多,所以B和E的pagerank值较高.
虽然很少有网页指向C,但是最重要的网页B指向了C,所以C的pagerank值比E还要大.
二.算法原理
求解步骤
如果一个网页有k条出 链,那么跳转任意一个出链上的概率是1/k ;
如果用n表示网 页的数目,则转移矩阵M是一个n*n的方阵;
如果网页j有k个出链,那么对每一个出链指向的网页i,有M[i][j]=1/k,而其他网页的M[i] [j]=0
1.求转移矩阵
则转移矩阵M表示如下:
A分向BCD,B分向AD,C分向A,D分向BC。可以将转移矩阵看成是ABCD,ABCD四行四列矩阵
2.Vn=M.V(n-1)
矩阵M中M[i][j]不为0表示用一个链接从j指向i,M的第一行乘以V 0 ,表示累加所有网页到网页A的概率即得到9/24。得到了V 1 后,再用 V 1 去右乘M得到V 2 ,一直下去,最终V会收敛,即V n =MV (n-1) ,上面的图示例,不断的迭代,最终V=[3/9,2/9,2/9,2/9]
3.终止点问题
要满足收敛性,需要具备一个条件:
图是强连通的,即从任意网页可以到达其他任意网页
。互联网上的网页不满足强连通的特性,因为有一些网页不指向任何网页,如果按照上面的计算,上网者到达这样的网页后便走投无路、四顾茫然,导致前面累 计得到的转移概率被清零,这样下去,最终的得到的概率分布向量所有元素几乎都为0。
4.陷阱问题
上网者跑到C网页后,就像跳进了陷阱,陷入了漩涡,再也不能从C中出来,将最终导致概率分布值全部转移到C上来,
这使得其他网页的概率分布值为0
,从而整个网页排名就失去了意义。
5.算法改进
(1)
解决终止点问题和陷阱问题
地址栏输入而跳转到各个网页的概率是1/n;上网者每一步查看当前网页的概率为a,那么从浏览器地址栏跳转的概率为(1-a);
(2)求解
三.算法总结
1.PR值
PR值:决定了网页在搜索结果中的排名
C点只进不出,统一除以节点个数4
2.PR值计算
在一般情况下,一个网页的PR值计算如下:
其中Mpi是所有对pi网页有出链的网页集合,L(pj)是网页pj的出链数目,N是网页总数,α一般取0.85。
根据上面的公式,我们可以计算每个网页的PR值,在不断迭代趋于平稳的时候,即为最终结果。
具体怎样算是趋于平稳,我们在下面的PR值计算方法部分再做解释。
3.PageRank算法的缺点
(1)
没有区分站内导航链接
。很多网站的首页都有很多对站内其他页面的链接,称为站内导航链接。这些链接与不同网站之间的链接相比,肯定是后者更能体现PageRank值的传递关系。
(2)没有过滤广告链接和功能链接(例如常见的 没有过滤广告链接和功能链接(例如常见的“ 分享到微博”)
。这些链接通常没有什么实际价值,前者链接到广告页面,后者常常链接到某个社交网站首页。
(3)对新网页不友好
。一个新网页的一般入链相对较少,即使它的内
容的质量很高,要成为一个高PR值的页面仍需要很长时间的推广。
#延伸------->TrustRank算法
针对PageRank算法的缺点,有人提出了TrustRank算法。
其最初来自于2004年斯坦福大学和雅虎的一项联合研究,用来检测垃圾网站。TrustRank算法的工作原理:
先人工去识别高质量的页面(即“种子”页面),那么由“种子”页面指向的页面也可能是高质量页面,即其TR值也高,与“种子”页面的链接越远,页面的TR值越低。“种子”页面可选出链数较多的网页,也可选PR值较高的网站。
…
TrustRank算法给出每个网页的TR值。将PR值与TR值结合起来,可以更准确地判断网页的重要性。
PageRanks算法实现
转自 https://blog.csdn.net/ten_sory/article/details/80927738
import numpy as np
if __name__ == '__main__':
# 读入有向图,存储边
f = open('input.txt', 'r')
edges = [line.strip('\n').split(' ') for line in f]
# print(edges)
nodes=[]
for edge in edges:
if edge[0] not in nodes:
nodes.append(edge[0])
if edge[1] not in nodes:
nodes.append(edge[1])
# print(nodes) # ['A', 'B', 'C', 'D', 'E']
N = len(nodes) # 5
# 将节点符号(字母),映射成阿拉伯数字,便于后面生成A矩阵/S矩阵
i = 0
node_to_num = {}
for node in nodes:
node_to_num[node] = i
i += 1
# print(node_to_num) # {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4}
for edge in edges:
edge[0] = node_to_num[edge[0]]
edge[1] = node_to_num[edge[1]]
# print(edges) # [[0, 1], [0, 2], [0, 3], [1, 3], [2, 4], [3, 4], [1, 4], [4, 0]]
# 生成初步的S矩阵
S=np.zeros([N,N])
for edge in edges:
S[edge[1],edge[0]]=1
# print(S)
# 计算比例:即一个网页对其他网页的PageRank值的贡献,即进行列的归一化处理
for j in range(N):
sum_of_col = sum(S[:, j])
for i in range(N):
S[i, j] /= sum_of_col
# print(S)
# 计算矩阵A
alpha = 0.85
A = alpha * S + (1 - alpha) / N * np.ones([N, N])
# print(A)
# 生成初始的PageRank值,记录在P_n中,P_n和P_n1均用于迭代
P_n = np.ones(N) / N # [0.2 0.2 0.2 0.2 0.2]
P_n1 = np.zeros(N) # [0. 0. 0. 0. 0.]
e = 100000 # 误差初始化
k = 0 # 记录迭代次数
print('loop...')
while e > 0.00000001: # 开始迭代
P_n1 = np.dot(A, P_n) # 迭代公式
e = P_n1 - P_n
e = max(map(abs, e)) # 计算误差
P_n = P_n1
k += 1
print('iteration %s:' % str(k), P_n1)
print('final result:', P_n)
结果:
iteration 65: [0.29633859 0.11396261 0.11396261 0.16239671 0.3133395 ]
iteration 66: [0.29633857 0.1139626 0.1139626 0.16239671 0.31333952]
iteration 67: [0.29633859 0.1139626 0.1139626 0.1623967 0.31333951]
iteration 68: [0.29633859 0.1139626 0.1139626 0.1623967 0.3133395 ]
iteration 69: [0.29633858 0.1139626 0.1139626 0.16239671 0.31333952]
iteration 70: [0.29633859 0.1139626 0.1139626 0.1623967 0.31333951]
iteration 71: [0.29633859 0.1139626 0.1139626 0.1623967 0.31333951]
final result: [0.29633859 0.1139626 0.1139626 0.1623967 0.31333951]
"""
最后的一个数组[0.29633859 0.1139626 0.1139626 0.1623967 0.31333951],分别为A, B, C, D, E的PageRank值,
E >A >D >B =C
可以看出,有3条边指向E。再看,指向A的这个点是E点,因此A的PageRank值也很高,可以说“A沾了E的光”
"""