前言
通过b站视频学习以及网上资料整理后进行学习笔记的撰写,只包含pr的一些简单原理及其应用。不包括pr的自定义实现。
一、pagerank简介
背景简介
PageRank算法 由Google创始人Larry Page 在斯坦福读大学时提出,又称PR,佩奇排名。主要针对网页进行排名,计算网站的重要性,优化搜素引擎的搜索结果。PageRank把互联网表示为由网页节点和引用链接构成的有向图,通过链接结构,计算网页节点重要度。来自重要网页节点的引用链接,权重更高。
PR值是表示其重要性的因子
两个假设
数量假设:在Web图模型中,如果一个页面节点接收到的其他网页指向的入链数量越多,那么这个页面越重要。
质量假设:指向页面一的入链质量不同,质量高的页面会通过链接向其他页面传递更多的权重。所以越是质量高的页面指向页面一,则页面一越重要。
入链和出链:1、入链数:指向该节点的链接数。2、出链数:由该节点指出的链接数。
优点:通过网页之间的链接来决定网页重要性,一定程度消除了人为对排名结果的影响。
二、pagerank算法介绍
- PR(a)表示当前节点a的PR值
- PR(Ti)表示其他各个节点(指向a)的PR值
- L(Ti) 表示其他节点(指向a)的出链数
- i代表循环次数
- 各个点的初始PR值为1/n,n代表网页个数
实例计算讲解
以上图进行讲解,初始值各个点PR值均为1/4,当i = 1时
L(C)=2,L(D)=1
因为C的出链数为2(指向A和D),D的出链数为1(指向A)
PR(C)和PR(D)的初始值均为1/4
其他同理计算后得到如下表:
矩阵化表达
转化为右边矩阵。从A->A的概率为0,A->B的概率是1/2,A->C的概率是1/2,A->D的概率是0.(因为A指向B和C,所以分别为1/2,而不指向A和D,所以为0)。其他数据同理可得。
上述矩阵成为M矩阵,那么V矩阵呢?V是上一次的PR值构成的列向量。
如,初始值的PR构成的列向量如下所示:
计算之后所得结果和前面的表格相同 :
pagerank的一些问题
Dead Ends问题
通过多次迭代后发现,所有的PR值都会归为0
解决办法:修正M矩阵
如何得到右边矩阵?
首先,由于A节点对应的是010,不满足第一行条件,改为000.
B节点对应的是000,满足第一行条件,所以改为111.
C节点对应010,同A,改为000
所以得到的矩阵a=[0,0,0,1,1,1,0,0,0]
再乘以1/3即可得到右边矩阵。
所以,该方法计算PR值的完整公式为:
- a=[a0,a1,a2,...,an],当有一列全为0时(该节点没有出链),ai=1,其他时候ai=0
- e为由1填满的列矩阵
- n为M矩阵的行/列数
- V为PR值的矩阵
Spider Traps问题
多次迭代后,发现A的PR值趋近于1,其他节点趋近于0
解决办法:Random Teleport
将节点图转换为转移概率矩阵,修正矩阵M
pagerank最终修正公式
- a=[a0,a1,a2,...,an],当有一列全为0时(该节点没有出链),ai=1,其他时候ai=0
- e为由1填满的列矩阵
- β表示跟随出链打开网页的概率
- 1-β表示随机跳转到其他网页的概率,比如说浏览A的时候有一定概率打开B或C或D
- 表示由1填满的n*n的矩阵
- n为M矩阵的行/列数
- V是各个节点PR值构成的列向量
pagerank的缺点
- 存放时间久的网站,pagerank值会越来越大,而新生成的网站增长值更慢。
- 查询结果可能会偏离我的搜索内容。
- 通过僵尸网站或链接,人为地去刷pr值。
pagerank代码应用Demo
import networkx as nx
import matplotlib.pyplot as plt
# 创建有向图
G = nx.DiGraph()
# 添加边
G.add_edge("A", "B")
G.add_edge("A", "C")
G.add_edge("B", "C")
G.add_edge("C", "A")
# 计算PageRank值
pagerank = nx.pagerank(G)
# 提取节点和PageRank值
nodes = pagerank.keys()
pr_values = pagerank.values()
# 绘制图形
plt.figure(figsize=(8, 6))
pos = nx.spring_layout(G) # 定义节点位置
nx.draw_networkx(G, pos, node_color='lightblue', node_size=[v * 10000 for v in pr_values], alpha=0.8, font_size=12, font_color='black')
nx.draw_networkx_labels(G, pos, font_size=12, font_color='black')
plt.title("PageRank Visualization", fontsize=14)
plt.axis('off')
# 输出节点的PageRank值
labels = {node: f"{node}: {pagerank[node]*100:.2f}%" for node in nodes}
plt.text(0.5, -0.1, '\n'.join(labels.values()), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, bbox=dict(facecolor='white', alpha=0.5))
plt.show()