自己对PageRank算法

来源:互联网 发布:软件售后服务合同范本 编辑:程序博客网 时间:2024/06/18 17:08

       最近在准备机器学习和高级计算机网络,都碰到了pagerank算法,刚开始没太注意,查了一下资料,才发现这是拉里佩奇在斯坦福大学里的原创算法,果然厉害,不得不佩服,我同样在我大华科的图书馆珍藏书籍里见到了这个算法真是太有缘了呀,以下就谈一谈我自己的看法,如果有不对的话还请大神们见谅呀!!

      
       PageRank的核心思想有2点:
      1.如果一个网页被很多其他网页链接到的话说明这个网页比较重要,也就是pagerank值会相对较高;
      2.如果一个pagerank值很高的网页链接到一个其他的网页,那么被链接到的网页的pagerank值会相应地因此而提高。
     下面是一张来自WikiPedia的图,每个球代表一个网页,球的大小反应了网页的pagerank值的大小。指向网页B和网页E的链接很多,所以B和E的pagerank值较高,另外,虽然很少有网页指向C,但是最重要的网页B指向了C,所以C的pagerank值比E还要大。

1.问题背景


2.数学建模

我们可以理解网页连接矩阵$G$,马尔科夫过程("网上冲浪"),转移矩阵$A$,概率$p$为用户点击当前网页中的某个链接地址的概率(一般都为0.85)。



最后得到一个等式$Ax=x$,这实际上就是求矩阵$A$的特征值为1的特征向量!

下面的内容使用圆盘定理解释了1是矩阵$A$的主特征值,所以我们可以使用幂法来求解。


3.求解PageRank

假设有如上图右侧所示的网页链接模型。

(1) 幂法

wiki上有一个PageRank的简便算法,它不考虑转移概率,而是采用的是迭代的方式,每次都更新所有网页的pagerank值,更新的方式就是将每个网页的pagerank值平摊分给它指向的所有网页,每个网页累计所有指向它的网页平摊给它的值作为它该回合的pagerank值,直到全部网页的pagerank值收敛了或者满足一定的阈值条件就停止。

后面的MapReduce框架下PageRank算法的实现就采用了这个思想。考虑转移概率的情况和这个算法类似,乘上一个转移概率再加上一个随机跳转的概率。



根据上面的思想,下面Matlab代码实现可以得到各个网页的PageRank值。

n=6;i=[2 3 4 4 5 6 1 6 1];j=[1 2 2 3 3 3 4 5 6];G=sparse(i,j,1,n,n);% Power methodfor j = 1:n   L{j} = find(G(:,j));   c(j) = length(L{j});endp = .85;delta = (1-p)/n;x = ones(n,1)/n;z = zeros(n,1);cnt = 0;while max(abs(x-z)) > .0001   z = x;   x = zeros(n,1);   for j = 1:n      if c(j) == 0         x = x + z(j)/n;%转移到任意一个网页      else         x(L{j}) = x(L{j}) + z(j)/c(j);%将上次的pagerank值平摊给所有指向的网页      end   end   x = p*x + delta;   cnt = cnt+1;end
得到的向量$x$保存了各个网页的pagerank值,虽然链接数目一样,但是网页①比网页④和网页⑤都高,而网页②的pagerank值第二高,因为网页①链接到了它上面,相当于沾了网页①的光。

x =    0.2675    0.2524    0.1323    0.1698    0.0625    0.1156

这篇文章给出该算法的一个Python版本实现,该博主使用第三方模块python-graph,python-graph模块实现了很多图算法,该模块的使用示例,使用前需要先安装,代码如下:

easy_install python-graph-coreeasy_install python-graph-dot
Python版本的算法实现:
# coding=utf-8


# python-graph https://code.google.com/p/python-graph/


# Import graphviz
import graphviz as gv


# Import pygraph
from pygraph.classes.digraph import digraph
from pygraph.readwrite.dot import write


# Define pagerank function
def pagerank(graph, damping_factor=0.85, max_iterations=100, \
             min_delta=0.00001):
    """
    Compute and return the PageRank in an directed graph.


    @type  graph: digraph
    @param graph: Digraph.


    @type  damping_factor: number
    @param damping_factor: PageRank dumping factor.


    @type  max_iterations: number
    @param max_iterations: Maximum number of iterations.


    @type  min_delta: number
    @param min_delta: Smallest variation required for a new iteration.


    @rtype:  Dict
    @return: Dict containing all the nodes PageRank.
    """


    nodes = graph.nodes()
    graph_size = len(nodes)
    if graph_size == 0:
        return {}
    # value for nodes without inbound links
    min_value = (1.0-damping_factor)/graph_size


    # itialize the page rank dict with 1/N for all nodes
    #pagerank = dict.fromkeys(nodes, 1.0/graph_size)
    pagerank = dict.fromkeys(nodes, 1.0)


    for i in range(max_iterations):
        diff = 0 #total difference compared to last iteraction
        # computes each node PageRank based on inbound links
        for node in nodes:
            rank = min_value
            for referring_page in graph.incidents(node):
                rank += damping_factor * pagerank[referring_page] / \
                        len(graph.neighbors(referring_page))


            diff += abs(pagerank[node] - rank)
            pagerank[node] = rank


        print 'This is NO.%s iteration' % (i+1)
        print pagerank
        print ''


        #stop if PageRank has converged
        if diff < min_delta:
            break


    return pagerank


# Graph creation
gr = digraph()


# Add nodes and edges
gr.add_nodes(["1","2","3","4"])


gr.add_edge(("1","2"))
gr.add_edge(("1","3"))
gr.add_edge(("1","4"))
gr.add_edge(("2","3"))
gr.add_edge(("2","4"))
gr.add_edge(("3","4"))
gr.add_edge(("4","2"))


# Draw as PNG
# dot = write(gr)
# gvv = gv.readstring(dot)
# gv.layout(gvv,'dot')
# gv.render(gvv,'png','Model.png')


pagerank(gr)

经过32次迭代之后得到的结果如下,和前面的结果一致:

This is NO.32 iteration
{'1': 0.2675338708706491, '3': 0.13227261904986046, '2': 0.2524037902400518, '5': 0.062477242064127136, '4': 0.1697488529161491, '6': 0.1155828978186352}

1 0
原创粉丝点击