0
点赞
收藏
分享

微信扫一扫

PageRank算法实现

十里一走马 2022-04-26 阅读 94
python

PageRank算法实现

  1. 迭代法实现大规模PageRank,网页数量不低于10000。解答在1.1 迭代法计算PageRank
  2. 代数法求小规模PageRank的稳态解,网页数量为5。解答在2.2 修正后PageRank的代数法计算
  3. 附加分,构造不存在稳态的情况,设计方法变为有稳态的情况。解答在2 修正的PageRank 的定义与计算

问题背景

值得一提的是,虽然 PageRank 算法经常被用于搜索引擎中,但是网络节点重要性分析的重要性对于很多领域都是非常重要的。

基本概念

  • 马尔可夫性质(Markov property):当一个随机过程在给定现在状态及所有过去状态情况下,其未来状态的条件概率分布仅依赖于当前状态;换句话说,在给定现在状态时,它与过去状态(即该过程的历史路径)是条件独立的。也就是说,系统的状态只与最邻近的上一个状态有关

P ( x n = x n ∣ x n − 1 = x n − 1 , x n − 2 = x n − 2 , . . . x 0 = x 0 ) = P ( x n = x n ∣ x n − 1 = x n − 1 ) P(x_n=x_n\mid x_{n-1}=x_{n-1}, x_{n-2}=x_{n-2},...x_0=x_0)=P(x_n=x_n\mid x_{n-1}=x_{n-1}) P(xn=xnxn1=xn1,xn2=xn2,...x0=x0)=P(xn=xnxn1=xn1)

  • 马尔可夫链:具有马尔可夫性质的离散时间的链。

  • 周期性 p i i ( n ) p_{ii}^{(n)} pii(n)表示在有向图中,经过 n n n个边之后从节点 i i i到节点 i i i的概率。记 d i d_i di是数集 { n ∣ p i i ( n ) > 0 } \{n\mid p_{ii}^{(n)}>0\} {npii(n)>0}最大公约数,如果 d i = 1 d_i=1 di=1则是非周期,如果 d i > 1 d_i>1 di>1则为周期的,且周期为 d i d_i di

  • 随机游走模型:给定一个含有 n n n 个结点的有向图,在有向图上定义随机游走模型,即一阶马尔可夫链,其中结点表示状态,有向边表示状态之间的转移,假设从一个结点到通过有向边相连的所有结点的转移概率相等

    转移矩阵 M M M :是一个 n n n 阶矩阵 M = [ m i j ] n × n M=[m_{ij}]_{n\times n} M=[mij]n×n。其中 m i j m_{ij} mij 的意义是从节点 j j j到节点 i i i的概率。

    **状态分布矩阵 R t R_t Rt **:某个时刻 t t t 访问各个节点的概率分布,其中在$ t+1 $时刻的状态分布矩阵 R t + 1 R_{t+1} Rt+1
    R t + 1 = M R t R_{t+1}=MR_t Rt+1=MRt

1 PageRank的基本定义

u u u为一个网页, N ( v ) N(v) N(v)表示网页 v v v向外链接数目, B ( u ) B(u) B(u)表示连接到网页 u u u的网页集合, R ( u ) R(u) R(u)表示网页 u u u的PageRank值, C C C为规范因子,作用是保证所有网页的PageRank总和为常数。
R ( u ) = c ∑ v ∈ B ( u ) R ( v ) / N ( v ) R(u)=c\sum_{v\in B(u)}{R(v)/N(v)} R(u)=cvB(u)R(v)/N(v)
值的一提的是, PageRank 的基本定义是理想化的情况,即要求马尔可夫链不可约且非周期,只有满足这个条件根据马尔可夫平稳分布定理,才会有当时间趋于无穷时状态分布收敛于唯一的平稳分布。

至于不符合上述的限制条件的马尔可夫链求解 PageRank 见本文 2 修正的PageRank 的定义与计算

1.1 迭代法计算PageRank

1.1.1 基本思路

假设 S S S为整个网页的总和,因为所有网页的 PageRank 值开始都是未知的,所以我们进行平均分配,给每个网页的 PageRank 都赋值 1 / S 1/S 1/S,再根据上式反复迭代计算,直到计算得到的 PageRank 值收敛于一个相对固定的数。也就是说,计算出的所有网页的重要程度趋于稳定,此时停止运算。

即极限
lim ⁡ t → + ∞ M t R 0 = R \lim_{t \to +\infty}{M^tR_0}=R t+limMtR0=R
存在。$ R $就是我们求取的 PageRank 值。

1.1.2 代码实现

# 运行环境:
# macOS 12.3.1
# PyCharm 2021.3.3 (Community Edition)
# Python 3.7

import numpy as np
import random

M = np.zeros((10000, 10000)) # 随机生成10000*10000的数据(可能含有自回路)
for i in range(len(M[0])):
    for j in range(len(M[0])):
        if i > 100:
            if random.random()>0.5:
                M[i, j] = 1
            else:
                M[i, j] = 0
        else:
            if random.random()>0.2:
                M[i, j] = 1
            else:
                M[i, j] = 0

for i in range(len(M[0])): # 将邻接矩阵转化为转移矩阵
    sum_i = np.sum(M[:, i])
    for j in range(len(M[0])):
        M[j, i] = M[j, i] / sum_i

R = np.ones((len(M[0]), 1)) * (1/len(M[0]))
alpha = 0.85 # 
R_1 = np.zeros((len(M[0]), len(M[0])))
e = 100000 # 初始化误差为100000
count = 0 # 记录迭代次数
while e > 0.00000000000001 or count < 1000: # 限制两个迭代条件,即迭代次数和误差大小
    # R_1 = np.dot(M, R)*alpha + (1-alpha)/len(M[0]) # 修正的pageRank
    R_1 = np.dot(M, R) # 基本的pageRank
    e = R - R_1
    e = np.max(np.abs(e))
    R = R_1
    count += 1
    print(f'iteration {count}: {e}')
print(f'final :{R}')

2 修正的PageRank 的定义与计算

在之前的定义中就已经提及,先前定义的 PageRank 具有一定的局限性(对于不存在稳态情况无法计算),主要体现在PageRank 值沉淀现象

2.1 修正的PageRank 的定义

所以引入衰减系数(damping factor) $ \alpha (0<\alpha<1)$,修正后的PageRank定义为:
R ( u ) = α ∑ v ∈ B ( u ) R ( v ) / N ( v ) + ( 1 − α ) R(u)=\alpha \sum_{v\in B(u)}{R(v)/N(v)} + (1-\alpha) R(u)=αvB(u)R(v)/N(v)+(1α)

2.2 修正后PageRank的代数法计算

修正后,PageRank 的平稳分布满足:
R = α M R + 1 − α n E R=\alpha MR + \frac {1-\alpha}{n}E R=αMR+n1αE
因此有:
R = ( E − α M ) − 1 1 − α n E R=(E-\alpha M)^{-1}\frac{1-\alpha}{n}E R=(EαM)1n1αE

2.2.1 代码实现

# 运行环境:
# macOS 12.3.1
# PyCharm 2021.3.3 (Community Edition)
# Python 3.7

import numpy as np
import random

M = np.zeros((5, 5))
for i in range(len(M[0])):
    for j in range(len(M[0])):
        if i > 2:
            if random.random()>0.5:
                M[i, j] = 1
            else:
                M[i, j] = 0
        else:
            if random.random()>0.2:
                M[i, j] = 1
            else:
                M[i, j] = 0
for i in range(len(M[0])): # 将邻接矩阵转化为转移矩阵
    sum_i = np.sum(M[:, i])
    for j in range(len(M[0])):
        M[j, i] = M[j, i] / sum_i

alpha = 0.85
A = alpha*M + (1-alpha)/len(M[0])*np.ones((len(M[0]), len(M[0])))
E = np.identity(len(M[0]))
B = np.ones(len(M[0]))
res = (1-alpha)/len(M[0])*np.linalg.inv(E-alpha*M)
res = np.dot(res, np.transpose(B))
print(f'final :{res}')

2.3 修正后的PageRank的迭代法计算

只需要将 1.1.2 代码实现 中的

  • R_1 = np.dot(M, R)*alpha + (1-alpha)/len(M[0]) # 修正的pageRank取消注释
  • R_1 = np.dot(M, R) # 基本的pageRank注释即可

在此不再赘述。

参考文献

[1]曹军.Google的PageRank技术剖析[J].情报杂志,2002(10):15-18.

[2]黄德才,戚华春.PageRank算法研究[J].计算机工程,2006(04):145-146+162.

举报

相关推荐

0 条评论