PageRank算法的实现
目标一 迭代法实现
题目
迭代法实现大规模PageRank,网页数量不低于10000
思路
首先创建一个txt文件,里面储存各个点之间的关系,然后通过python语言读取,将其转化为矩阵,并通过公式将其转化为相应矩阵,然后进行迭代,直至误差小于 0.00000001结束。
原理
源代码
import numpy as np
if __name__ == '__main__':
file = open('input2.txt', 'r')
edges_in = []
edges_out = []
while True:
lines = file.readline().strip('\n')
if not lines:
break
else:
this_line = lines.split(' ')
edges_out.append(this_line[0])
edges_in.append(this_line[1])
# 根据边获取节点的集合
nodes = []
for edge in edges_out:
if edge not in nodes:
nodes.append(edge)
for edge in edges_in:
if edge not in nodes:
nodes.append(edge)
length = len(nodes) # 数据的个数
i = 0
node_to_num = {}
for node in nodes:
node_to_num[node] = i
i += 1
for i in range(len(edges_in)):
edges_in[i] = node_to_num[edges_in[i]]
edges_out[i] = node_to_num[edges_out[i]]
# 生成初步的S矩阵
S = np.zeros([length, length])
for i in range(len(edges_in)):
S[edges_in[i], edges_out[i]] = 1
# 计算比例:即一个网页对其他网页的PageRank值的贡献,即进行列的归一化处理
for j in range(length):
sum_of_col = sum(S[:, j])
for i in range(length):
if sum_of_col != 0:
S[i, j] /= sum_of_col
else:
S[i, j] = 1/length # 判断是零的情况
# 计算矩阵A
a = 0.85
A = a * S + (1 - a) / length * np.ones([length, length])
# 准备进行迭代
PageRank1 = np.ones(length) / length
PageRank2 = np.zeros(length)
judge = 1 # 误差判断
while judge > 0.00000001: # 开始迭代
PageRank2 = np.dot(A, PageRank1) # 迭代公式
judge = PageRank2 - PageRank1
judge = max(map(abs, judge))
PageRank1 = PageRank2
print('最终结果:', PageRank1)
运行截图
注:因为10000个数据不太好展示,所以附带运行了一下10以内的数据进行简单展示。
10以内的简单展示
目标二 代数法实现
题目
代数法求小规模PageRank的稳态解,网页数量为5
思路
利用上一个迭代法部分代码求得S与A,然后进行求逆等相应操作。
原理
源代码
import numpy as np
if __name__ == '__main__':
file = open('input.txt', 'r')
edges_in = []
edges_out = []
while True:
lines = file.readline().strip('\n')
if not lines:
break
else:
this_line = lines.split(' ')
edges_out.append(this_line[0])
edges_in.append(this_line[1])
# 根据边获取节点的集合
nodes = []
for edge in edges_out:
if edge not in nodes:
nodes.append(edge)
for edge in edges_in:
if edge not in nodes:
nodes.append(edge)
length = len(nodes) # 数据的个数
i = 0
node_to_num = {}
for node in nodes:
node_to_num[node] = i
i += 1
for i in range(len(edges_in)):
edges_in[i] = node_to_num[edges_in[i]]
edges_out[i] = node_to_num[edges_out[i]]
# 生成初步的S矩阵
S = np.zeros([length, length])
for i in range(len(edges_in)):
S[edges_in[i], edges_out[i]] = 1
# 计算比例:即一个网页对其他网页的PageRank值的贡献,即进行列的归一化处理
for j in range(length):
sum_of_col = sum(S[:, j])
for i in range(length):
if sum_of_col != 0:
S[i, j] /= sum_of_col
else:
S[i, j] = 1 / length
# 计算矩阵A
a = 0.85
A = a * S + (1 - a) / length * np.ones([length, length])
E = np.identity(length)
B = np.ones(length)
PageRank = (1 - a) / length * np.linalg.inv(E - a * S)
PageRank = np.dot(PageRank, np.transpose(B))
print('最终结果:', PageRank)
运行截图
附加
题目
构造不存在稳态的情况,设计方法变为有稳态的情况
思路
pagerank的计算公式按迭代方式计算,保证矩阵A是正确的。
A=d*P+(1-d)ee^T/n
0<d<1
源代码
注:本人上述代码均使用了该方法避免不收敛
运行截图
补充:
1.代数求解方法需要解方程组
矩阵:S
0
0
0
0
1
0
0
1
0
1
0
0
1
0
1
0
\begin{matrix} 0&0&0&0\\ 1&0&0&1\\ 0&1&0&0\\ 1&0&1&0\\ \end{matrix}
0101001000010100
矩阵:(E-aS)-1
1
0
0
0
−
0.425
1
0
−
0.85
0
−
0.85
1
0
−
0.425
0
−
0.85
1
\begin{matrix} 1&0&0&0\\ -0.425&1&0&-0.85 \\ 0&-0.85&1&0\\ -0.425&0&-0.85&1\\ \end{matrix}
1−0.4250−0.42501−0.850001−0.850−0.8501
方程:
{
1
p
1
+
0
p
2
+
0
p
3
+
0
p
4
=
0.375
−
0.425
p
1
+
1
p
2
+
0
p
3
+
−
0.85
p
4
=
0.375
0
p
1
+
−
0.85
p
2
+
1
p
3
+
0
p
4
=
0.375
−
0.425
p
1
+
0
p
2
+
−
0.85
p
3
+
1
p
4
=
0.375
\begin{cases} 1p_1+0p_2+0p_3+0p_4=0.375\\ -0.425p_1+1p_2+0p_3+-0.85p_4=0.375\\ 0p_1+-0.85p_2+1p_3+0p_4=0.375\\ -0.425p_1+0p_2+-0.85p_3+1p_4=0.375\\ \end{cases}
⎩
⎨
⎧1p1+0p2+0p3+0p4=0.375−0.425p1+1p2+0p3+−0.85p4=0.3750p1+−0.85p2+1p3+0p4=0.375−0.425p1+0p2+−0.85p3+1p4=0.375
解之得:
0.0375
0.32640914
0.31494776
0.3211431
\begin{matrix} 0.0375&0.32640914&0.31494776&0.3211431\\ \end{matrix}
0.03750.326409140.314947760.3211431
2.变成稳态的方法
利用衰减系数进行判断,用户会有概率随机跳转到一个网页,这样可以保证存在稳态