初步理解pagerank算法

初步理解pagerank算法

第一次写不是课程要求的博客,可能有不严谨的地方,如果有写错的希望能在评论区指出。

算法思想

pagerank算法用于网页排序,根据给网页的重要程度给各个网页打分,根据分数高低进行排序。而怎么判断网页的重要程度?该算法认为,若是对于某个网页A,引用(链接到)网页A的网页越多,重要度越强(即引用网页A的网页也被好多网页引用),那么网页A本身的重要度越强

算法描述

下面说说如何量化。我们需要知道所有被排名网页的引用关系。计网页wi的重要度为PR(wi),采用如下方式计算最终的重要度。

初始化每个网页的PR值。

设定PR值在0到1之间(为了和概率挂上联系)。首先,等值初始化所有网页的PR值,即若网页总数为n,则所有网页网页wi的初始PR(wi)=1/n。
可以证明,所有随机初始化(不能全是0)得到的PR值向量在后续的迭代计算中会收敛到一个定值。

迭代得到最终的PR值

利用迭代法得到最终的PR值。为了利用到上面“算法思想”的想法,跟自然的想到,可以将所有引用的wi的网页的PR值加和表示wi的新的PR。但这样就会出现个问题:
1.若是某网页wk引用的网页数量多于wj引用的网页,而二者都引用了wi,那么wj对wi的PR的贡献度很有可能比wk要高。
因此,pagerank算法使用所有引用的wi的网页的PR值的加权求和表示wi的新的PR。各个引用wi的网页(使用wj表示)的“转移权值”使用1/n(wj),其中nj是网页wj的引用网页总数。,即PR的迭代公式如下:
P R ( w i ) = Σ w j ∈ M ( w i ) P R ( w i ) n ( w j ) PR(w_i)=\Sigma_{w_j \in M(w_i)} \frac{ PR(w_i)}{n(w_j)} PR(wi)=ΣwjM(wi)n(wj)PR(wi)
其中M(wi)表示引用了网页wi的所有网页的集合。
后面的举例会更清楚的说明这些步。

矩阵形式描述:

计所有的PR值构成的向量为P
根据每个网页的引用与被引用关系,可以得到个有向图G(这里用邻接矩阵表示,不知道邻接矩阵的请自行百度),其中节点数即为网页的总数,节点i指向节点j表示网页wj引用了网页wi
Gij若不为0,则表示网页wj引用了网页wi,其值即上面讲的wj对wi的“转移权值”,所以,G的每一列的所有非0元素都相等,且都为1/n(wj)。G每一列的加和结果是1(除非wj一个其他网页都不引用,则该列所有元素为0)。
迭代计算的公式为:
P n e w = G P o l d \textbf{P}_{new} = \textbf{G}\textbf{P}_{old} Pnew=GPold

举个例子

下图表示,总共4个网页需要排序。其中A、B互相引用;B引用了C;D引用了B和C。
网络
首先,初始化PR值,即P=(0.25, 0.25, 0.25, 0.25)。

迭代法:

重复计算下式直到收敛(即P中各个元素不再变化或者在一个很小的阈值之内变化)
P R A = 1 2 P R B PR_A=\frac{1}{2}PR_B PRA=21PRB
P R B = P R A + 1 2 P R D PR_B=PR_A+\frac{1}{2}PR_D PRB=PRA+21PRD
P R C = 1 2 P R B + 1 2 P R D PR_C=\frac{1}{2}PR_B+\frac{1}{2}PR_D PRC=21PRB+21PRD
P R D = 0 PR_D=0 PRD=0
代码:
(引用了numpy库,graph是我自己写的一个类的对象,graph包含一个字典,长度是图的节点数量,键是节点,值是与该节点邻接的所有节点与边上权值构成的小字典。代码写的比较烂,还没有运行对不对):

	@staticmethod
    def pagerank_v1(graph, d=0.85,threshold=1e-5, iteror=100):
        '''
        迭代
        '''
        i = 0
        error = 2**32
        num = len(graph.nodes)
        PR = []
        pr = []
        for k in range(num):
            PR.append(1/num)
            pr.append(1/num)
        PR = np.asarray(PR)
        pr = np.asarray(pr)
        while (i <= iteror) & (error > threshold):
            for k in range(num):
                pr[k] = Graph.add(graph.nodes[k], PR[k])
            error = max(np.sqrt(PR - pr))
            for k in range(num):
                PR[k] = pr[k]
            i += 1
        return PR
        
    @staticmethod
    def add(node_edge, A):
        result = 0
        for i in node_edge:
            result += A * node_edge[i]
        return result

矩阵法:

构造图的邻接矩阵G,如下:
矩阵
迭代计算
P n e w = G P o l d \textbf{P}_{new} = \textbf{G}\textbf{P}_{old} Pnew=GPold
直到P收敛。
注意,若是P能够收敛(设收敛时为Pfinal),则有Pfinal=G Pfinal,即PfinalG特征值为1时候的特征向量,可以利用已有的计算矩阵特征值的工具进行计算。
代码:

	import numpy as np
    @staticmethod
    def pagerank_v2(graph, d=0.85):
        '''
        特征值
        '''
        m1 = Graph.get_graph_from_matrix(graph)
        m1 = np.matrix(m1)
        eigenvalue,featurevector=np.linalg.eig(m1)
        return featurevector[0]

几点说明:

可以证明,若G的所有列之和为1,G必有特征值为1的特征向量。简要说一下证明,G的转置左乘元素全是1的列向量,结果还是元素全是1的列向量,故G的转置有1特征值,故G有值为1的特征值。

特征值1是G的最大特征值。简要说一下证明,设r是G的特征值,x是G对应的特征向量,||G||为G的1范数,则||rx||=||Gx||。而|r|·||x||=||rx||,||G||·||x||>=||Gx||,故|r|<=||G||。而由于G的每列加和为1,故||G||=1。即|r|<=1。

算法的改进:

从上面给出的例子不难看出,PR(D)最终为0,从而其他的PR值也逐渐变成0。事实上,上述算法会产生以下问题:排名不唯一问题(即G特征值为1的特征向量不止一个)。
为了改进这些问题,加上一个平滑参数d(通常取0.85),将迭代公式修改为:
P R ( w i ) = 1 − d N + d ⋅ Σ w j ∈ M ( w i ) P R ( w i ) n ( w j ) PR(w_i)=\frac{1-d}{N} +d· \Sigma_{w_j \in M(w_i)} \frac{ PR(w_i)}{n(w_j)} PR(wi)=N1d+dΣwjM(wi)n(wj)PR(wi)
矩阵形式修改为:
P n e w = d ⋅ G P o l d + 1 − d N \textbf{P}_{new} =d· \textbf{G}\textbf{P}_{old} + \frac{\textbf1-\textbf d}{N} Pnew=dGPold+N1d
其中,N为总节点数量。
此外,上面例子还有一个悬挂节点的问题,即有些网页不会引用其他网页,造成G某一列和不为1,从而使1可能不是G的特征值。但我们仍然可以使用该算法为每个网页打分。

算法证明:

可以参照下面其他博主的链接,写的非常详细
证明
证明
证明
或者论文
THE $25,000,000,000∗ EIGENVECTOR
THE LINEAR ALGEBRA BEHIND GOOGLE

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值