关于PageRank算法的一些整理

关于PageRank算法

参考文献:PageRank算法PageRank算法–从原理到实现

1、算法中心思想

在这里插入图片描述

(1)数量假设:在网页模型图中,一个网页接收到的其他网页指向的入链(in-links)越多,说明该网页越重要。

在这里插入图片描述

(2)质量假设:当一个质量高的网页指向(out-links)一个网页,说明这个被指向的网页质量也高。

在这里插入图片描述

可以这样类比:在一次投票过程中,得票数多的人,其声望排名肯定相对较高;此外,被声望较高的人投票的人,说明其声望排名也较高。

2、算法和公式

P R ( a ) i + 1 = ∑ i = 0 n P R ( T i ) i L ( T i ) PR(a)_{i+1} = \sum_{i=0}^n \frac {PR(Ti)_i}{L(Ti)} PR(a)i+1=i=0nL(Ti)PR(Ti)i

P R ( T i ) PR(Ti) PR(Ti)代表的是其他节点(指向节点a的节点)的PR值;

L ( T i ) L(Ti) L(Ti)代表的是其他节点(指向节点a的节点)的出链数;

i i i代表循环次数。当 i = 0 i=0 i=0时,所有节点的初始值初始化为 1 N \frac 1 N N1(N为所有节点数目,及网页数目)。

PR值需要通过多次循环迭代才能达到一个稳定值

【示例】

可见,节点A的PR值与其在上一次循环中的PR值没有任何关系。

【矩阵化表达】

通过矩阵化表达,快速求解PR值:
P R ( a ) = M ∗ V PR(a) = M*V PR(a)=MV
矩阵M为图的马尔科夫矩阵,V为上一次循环各节点PR值构成的矩阵。

3、Dead Ends问题

如上图所示,B没有任何出链,则造成Dead Ends问题。经过多次循环之后,其会导致网站的权重变为0。

【解决方案】Teleport——将节点图转化成列转移概率矩阵,再修正马尔科夫矩阵M
修 正 过 程 : M ← M + a T ( e e T n ) \bold {修正过程}: M \leftarrow M + a^T(\frac {ee^T} n) MM+aT(neeT)
a = [ a 0 , a 1 , . . . , a n ] \bold a=[\bold a_0,\bold a_1,...,\bold a_n] a=[a0,a1,...,an] a i \bold a_i ai为行向量),当修正前的M中第 i i i列数值全为0(即对应节点无出链)时,则 a i \bold a_i ai中的元素全为1,否则矩阵 a i \bold a_i ai中元素全为0。 e e T ee^T eeT为由元素1填满的n*n矩阵, n n n为M矩阵的行数(或列数)。

【示例】

如上图,因为第1列元素全为0,所以有 a 1 = [ 1 , 1 , 1 ] \bold a_1 =[1,1,1] a1=[1,1,1],而第0列和第2列不全为0,所以 a 0 , a 2 \bold a_0,\bold a_2 a0,a2元素全为0。

对M矩阵进行修正的过程如上图所示。

4、Spider Traps问题

A节点与其他节点之间不存在出链(更具体地说,节点A存在自环),此为Spider Traps问题。由表格可见,其会导致网站权重变为向某一个含自环的节点偏移(因为此节点PR值最终会趋于1)。

【解决方案】Random Teleport——将节点图转化成列转移概率矩阵,再修正马尔科夫矩M(随机浏览模型)
修 正 过 程 : M ← β M + ( 1 − β ) e e T n \bold {修正过程}: M \leftarrow \beta M + (1-\beta )\frac {ee^T} n MβM+(1β)neeT
β \beta β为跟随出链打开网页的概率; 1 − β 1-\beta 1β为随机跳转到其他网页的概率,例如浏览网页A时有一定概率会打开网页B或C。

e e T ee^T eeT为由元素1填满的n*n矩阵, n n n为M矩阵的行数(或列数)。

【示例】

β \beta β值取值范围一般是在[0.8 , 0.9]。

如上图所示,修正后的M矩阵中,A所在的列中元素值已然发生了改变。

【思考】在使用 β \beta β解决Spider Traps问题时能否顺便解决Dead Ends问题?

​ 答:不能,使用 β \beta β解决Dead Ends问题时,修正后的M不满足转移概率矩阵的性质:列之和为1。因此,禁用 β \beta β是不足以解决Dead Ends问题的。

5、最终修正公式

当同时遇到Dead Ends问题和Spider Traps问题时,修正公式如下:
P R ( a ) = [ β ( M + a T ( e e T n ) ) + ( 1 − β ) e e T n ] ∗ V PR(a) = \bigg [\beta \bigg ( M + a^T(\frac {ee^T} n) \bigg) +(1-\beta )\frac {ee^T} n \bigg]*V PR(a)=[β(M+aT(neeT))+(1β)neeT]V

6、PageRank的优缺点
优点

(1)通过网页之间的链接来决定网页的重要性,一定程度消除了对认为排名结果的影响;

(2)离线计算PageRank值,提升了查询效率。

缺点

(1)存在时间长的网站,PageRank值会越来越大(因为其入链会越来越多);新生的网站,PageRank值增长慢(因为其初始入链相对较少且增长慢);

(2)非查询相关的特性,查询结果会偏离搜索内容;

(3)可以通过“僵尸网站”或链接,人为刷PageRank值;

7、附录

代码摘抄自PageRank算法–从原理到实现,感谢!

from pygraph.classes.digraph import digraph


class PRIterator:
    __doc__ = '''计算一张图中的PR值'''

    def __init__(self, dg):
        self.damping_factor = 0.85  # 阻尼系数,即α
        self.max_iterations = 100  # 最大迭代次数
        self.min_delta = 0.00001  # 确定迭代是否结束的参数,即ϵ
        self.graph = dg

    def page_rank(self):
        #  先将图中没有出链的节点改为对所有节点都有出链
        for node in self.graph.nodes():
            if len(self.graph.neighbors(node)) == 0:
                for node2 in self.graph.nodes():
                    digraph.add_edge(self.graph, (node, node2))

        nodes = self.graph.nodes()
        graph_size = len(nodes)

        if graph_size == 0:
            return {}
        page_rank = dict.fromkeys(nodes, 1.0 / graph_size)  # 给每个节点赋予初始的PR值
        damping_value = (1.0 - self.damping_factor) / graph_size  # 公式中的(1−α)/N部分

        flag = False
        for i in range(self.max_iterations):
            change = 0
            for node in nodes:
                rank = 0
                for incident_page in self.graph.incidents(node):  # 遍历所有“入射”的页面
                    rank += self.damping_factor * (page_rank[incident_page] / len(self.graph.neighbors(incident_page)))
                rank += damping_value
                change += abs(page_rank[node] - rank)  # 绝对值
                page_rank[node] = rank

            print("This is NO.%s iteration" % (i + 1))
            print(page_rank)

            if change < self.min_delta:
                flag = True
                break
        if flag:
            print("finished in %s iterations!" % node)
        else:
            print("finished out of 100 iterations!")
        return page_rank


if __name__ == '__main__':
    dg = digraph()

    dg.add_nodes(["A", "B", "C", "D", "E"])

    dg.add_edge(("A", "B"))
    dg.add_edge(("A", "C"))
    dg.add_edge(("A", "D"))
    dg.add_edge(("B", "D"))
    dg.add_edge(("C", "E"))
    dg.add_edge(("D", "E"))
    dg.add_edge(("B", "E"))
    dg.add_edge(("E", "A"))

    pr = PRIterator(dg)
    page_ranks = pr.page_rank()

    print("The final page rank is\n", page_ranks)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值