PageRank算法 Google民主表决式网页排名技术

博客简介

本篇博客介绍PageRank算法原理。这原本是一个小组的任务,我们在网上搜集了相关资料整理成了PPT,用于展示。如果不嫌弃的话可以下载来看看:https://download.csdn.net/download/weixin_44307065/12197391

  • Google民主表决式网页排名技术简介
  • PageRank算法原理
  • PageRank算法证明
  • 举例说明

Google民主表决式网页排名技术简介

Google革命性的发明是它名为 “Page Rank” 的网页排名算法,这项技术彻底解决了搜索结果排序的问题。其实最先试图给互联网上的众多网站排序的并不是 Google。Yahoo! 公司最初第一个用目录分类的方式让用户通过互联网检索信息,但由于当时计算机容量和速度的限制,当时的 Yahoo! 和同时代的其它搜索引擎都存在一个共同的问题: 收录的网页太少,而且只能对网页中常见内容相关的实际用词进行索引。那时,用户很难找到很相关信息。我记得 1999 年以前查找一篇论文,要换好几个搜索引擎。后来 DEC 公司开发了 AltaVista 搜索引擎,只用一台 ALPHA 服务器,却收录了比以往引擎都多的网页,而且对里面的每个词进行索引。AltaVista 虽然让用户搜索到大量结果,但大部分结果却与查询不太相关,有时找想看的网页需要翻好几页。所以最初的 AltaVista 在一定程度上解决了覆盖率的问题,但不能很好地对结果进行排序。
在这里插入图片描述

PageRank算法原理

描述

算法的原理很简单,在互联网上,如果一个网页被很多其他网页所链接,说明它收到普遍的承认和信赖,那么它的排名就高。比如我们要找李开复博士,有100个人举手说自己是李开复,那么谁是真的呢?如果大家都说创新工厂的那个是真的,那么他就是真的。这就是所谓的民主表决。但是,那么多网页,我们不可能一样对待。有些可靠的链接,相应的权重就要大一点。但是麻烦来了,一开始的时候,我们怎么给网页设置初始权重呢?这有点类似“先有鸡还是先有蛋”的问题。破解这个问题的是谷歌的创始人之一:布林。他把问题变成一个二维矩阵相乘的问题,用迭代的方法解决这个问题。他们先假设所有网页的排名相同,然后算出哥哥网页第一次迭代排名,然后根据这个第一次的排名算第二次的…他们从理论上证明了无论初始值如何,这个算法保证网页的排名的估计值能收敛到排名的真实值。且算法不需要人工干预。由于互联网上的网页量很大,在计算矩阵乘法时,谷歌利用稀疏矩阵减少了计算量。并利用MapReduce实现并行计算自动化。
  网页排名算法的高明之处在于它把整个互联网当作一个整体来对待。这无意识中符合了系统论的观点。而当时大部分人只注意了网页内容和查询语句,忽略了网页之间的关系,就算发现了,也只是摸到一些皮毛,没有从根本上解决问题。这个算法对当时的搜索结果影响非常大。当时一般的搜索引擎,前十个只有三四个是相关的。而Google能达到七八条。现在的搜索引擎基本都能达到这一点。
(1)

要点

  • 将整个互联网当作一个整体,网页间相互链接
  • 网页间的链接关系抽象成一张图Graph,用二维矩阵来描述链接关系
  • 网页的可靠链接越多,相应权重越大
  • 假设所有网页的排名相同,权重一致
  • 将二维矩阵相乘,迭代出新的矩阵
  • 经过有限次的迭代,矩阵将收敛到排名的真实值
  • 上述收敛假设可在理论上得到证明

PageRank算法证明

(1)证明思路:

在这里插入图片描述

(2)证明极限存在

在这里插入图片描述
在这里插入图片描述

(3)证明极限的值与P0无关

在这里插入图片描述

算法实现

如下图所示,A,B,C,D代表4张网页,相互之间的链接关系已经在图中标明,请用PageRank算法给各个网页排序权值

在这里插入图片描述

# -*- coding: utf-8 -*-

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"])

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

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

    print("The final page rank is\n", page_ranks)

这是最后得到的计算结果,给出了各个网页的排名权重:

This is NO.1 iteration
{'A': 0.14375, 'B': 0.2907291666666667, 'C': 0.07822916666666667, 'D': 0.26828385416666667}
This is NO.2 iteration
{'A': 0.16105989583333336, 'B': 0.31117491319444446, 'C': 0.08313363715277779, 'D': 0.28604656684027785}
This is NO.3 iteration
{'A': 0.1697493381076389, 'B': 0.3287352276114005, 'C': 0.08559564579716436, 'D': 0.29806441645959925}
This is NO.4 iteration
{'A': 0.17721247173484522, 'B': 0.3410649543155322, 'C': 0.08771020032487281, 'D': 0.3072164761851158}
This is NO.5 iteration
{'A': 0.18245260558410117, 'B': 0.3503289096728438, 'C': 0.08919490491549534, 'D': 0.313900360704625}
This is NO.6 iteration
{'A': 0.18638978661095862, 'B': 0.35712574613870285, 'C': 0.09031043953977161, 'D': 0.3188527552575262}
This is NO.7 iteration
{'A': 0.1892784421089487, 'B': 0.362153733899766, 'C': 0.09112889193086882, 'D': 0.3225037869795079}
This is NO.8 iteration
{'A': 0.19141533690740056, 'B': 0.36586256438967857, 'C': 0.09173434545709683, 'D': 0.3252001289612425}
This is NO.9 iteration
{'A': 0.1929915898656134, 'B': 0.36860106007897986, 'C': 0.0921809504619238, 'D': 0.32719020888812544}
This is NO.10 iteration
{'A': 0.19415545053356645, 'B': 0.3706223885394171, 'C': 0.0925107109845105, 'D': 0.3286593304505967}
This is NO.11 iteration
{'A': 0.19501451512925227, 'B': 0.3721145435029619, 'C': 0.09275411261995481, 'D': 0.32974378933567516}
This is NO.12 iteration
{'A': 0.19564868098875882, 'B': 0.3732160138821389, 'C': 0.092933792946815, 'D': 0.3305443228515168}
This is NO.13 iteration
{'A': 0.196116805899909, 'B': 0.3740291027620968, 'C': 0.09306642833830756, 'D': 0.3311352610997601}
This is NO.14 iteration
{'A': 0.19646236867389114, 'B': 0.37462930972573194, 'C': 0.09316433779093583, 'D': 0.3315714815466674}
This is NO.15 iteration
{'A': 0.19671745663343607, 'B': 0.3750723720274741, 'C': 0.0932366127128069, 'D': 0.3318934916303693}
This is NO.16 iteration
{'A': 0.19690575811167652, 'B': 0.37539943268412224, 'C': 0.09328996479830835, 'D': 0.33213119376762246}
This is NO.17 iteration
{'A': 0.19704475889075196, 'B': 0.3756408630548588, 'C': 0.09332934835237973, 'D': 0.33230666125021746}
This is NO.18 iteration
{'A': 0.197147366798315, 'B': 0.37581908265554076, 'C': 0.09335842059285591, 'D': 0.33243618822538823}
This is NO.19 iteration
{'A': 0.19722311012860483, 'B': 0.3759506411946847, 'C': 0.09337988120310471, 'D': 0.3325318027334847}
This is NO.20 iteration
{'A': 0.197279022507741, 'B': 0.37604775536732193, 'C': 0.09339572304385996, 'D': 0.3326023836622527}
This is NO.21 iteration
{'A': 0.1973202960311118, 'B': 0.37611944332172975, 'C': 0.09340741720881501, 'D': 0.33265448524804286}
This is NO.22 iteration
{'A': 0.19735076341173516, 'B': 0.3761723620941614, 'C': 0.09341604963332496, 'D': 0.33269294571166974}
This is NO.23 iteration
{'A': 0.19737325389001859, 'B': 0.37621142579042455, 'C': 0.09342242193550528, 'D': 0.3327213365416152}
This is NO.24 iteration
{'A': 0.19738985596093042, 'B': 0.3762402619159698, 'C': 0.09342712585559695, 'D': 0.3327422941471415}
This is NO.25 iteration
{'A': 0.19740211131428717, 'B': 0.37626154823078506, 'C': 0.0934305982057147, 'D': 0.3327577646786558}
This is NO.26 iteration
{'A': 0.19741115799808365, 'B': 0.3762772614096478, 'C': 0.09343316143279037, 'D': 0.33276918474976247}
This is NO.27 iteration
{'A': 0.19741783609910032, 'B': 0.3762888605987098, 'C': 0.09343505356141177, 'D': 0.33277761484306345}
This is NO.28 iteration
{'A': 0.19742276575445167, 'B': 0.3762974229136986, 'C': 0.09343645029709464, 'D': 0.33278383778794696}
This is NO.29 iteration
{'A': 0.1974264047383219, 'B': 0.37630374346227946, 'C': 0.09343748134252455, 'D': 0.33278843145513914}
This is NO.30 iteration
{'A': 0.19742909097146877, 'B': 0.3763084091787844, 'C': 0.09343824244191616, 'D': 0.3327918224185282}
This is NO.31 iteration
{'A': 0.19743107390098336, 'B': 0.37631185332769435, 'C': 0.09343880427194529, 'D': 0.3327943255673689}
finished in D iterations!
The final page rank is
 {'A': 0.19743107390098336, 'B': 0.37631185332769435, 'C': 0.09343880427194529, 'D': 0.3327943255673689}

发布了191 篇原创文章 · 获赞 377 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_44307065/article/details/104550015