PageRank计算方法(通过power iteration方式来实现)

来源:互联网 发布:arp ip 对应mac地址 编辑:程序博客网 时间:2024/05/19 15:21

PageRank
对Web图中的每个节点赋一个0 到1 之间的分值,这个分值被称为PageRank。节点的PageRank 值依
赖于Web 图的链接结构。

考虑一个网上的随机冲浪者,它从某个网页(即Web 图中的一个节点)出发,在Web 中进行如下随机游走过程:在每一步中,冲浪者都会从当前网页A 的链出网页中随机选出一个网页作为下一步的访问目标。图21-1 给出了某个冲浪者处于节点A 的例子,其中A 有三个链接分别指向B、C、D,那么下一步他将以1/3 的等概率分别访问这三个节点。
这里写图片描述
当冲浪者在 Web 上进行节点间的随机游走时,他对某些节点的访问次数会比其他节点更多。直观地看,这些访问频繁的节点具有很多从其他频繁访问节点中指向的入链接。PageRank的思路就是,在随机游走过程中访问越频繁的网页也越重要。有时候冲浪者所在的当前网页A可能不存在出链,这时应该怎么做?为了解决这个问题,我们为冲浪者引入一个被称为随机跳转(teleport)①的额外操作。基于这个操作,冲浪者可以从一个节点跳到Web图的任一其他节点。由于他有可能在浏览器中输入一个URL,所以上述操作是有可能发生的。随机跳转操作的目标节点可以从满足均匀分布的所有Web网页中随机选择来实现。换句话说,假如Web图中所有的节点数目是N,那么随机跳转操作使得冲浪者以1/N的概率跳到每个节点。当然,冲浪者也以1/N的概率跳到其当前位置。

给Web 图中的每个节点分配PageRank 值时,有两种使用随机跳转操作的方法:(i) 当节点没有出链接时,冲浪者调用随机跳转操作;(ii) 当节点包含出链接时,冲浪者将以0 < α < 1 的概率调用随机跳转操作,而以1−α 的概率继续进行随机游走(从满足均匀分布的出链接中随机选择一个出链前行)。其中α 是一个事先选定的固定参数,一个典型的α 取值为0.1。


马尔科夫链
马尔科夫链是一个离散时间随机过程(discrete-time stochastic process),这个过程中的每一
步都需要做一个随机选择。一个马尔科夫链包括N 个状态(state)。在下面的介绍中,每个Web
网页都对应我们所构造的马尔科夫链中的一个状态。

马尔科夫链通过一个的转移概率矩阵(transition probability matrix)P 来刻画,其中
每个元素的值在[0,1]之间,并且P 中每一行的元素之和为1。在任一步,马尔科夫链都可能处
于N 个状态之一,那么,元素Pij 给出的就是从当前状态i 到下一个状态j 的条件转移概率。Pij
被称为转移概率,它仅仅依赖于当前的状态i,这种性质被称为马尔科夫性。因此,基于马尔科
夫性,我们有这里写图片描述这里写图片描述

满足上述性质的非负矩阵被称为随机矩阵(stochastic matrix)。随机矩阵的一个重要性质是,
它的最大特征值是1,与该特征值对应的有一个主左特征向量(principal left eigenvector)。

马尔科夫链中,下一个状态的分布仅仅依赖于当前的状态,而和如何到达当前状态无关。
图21-2 给出了包含3 个状态的简单马尔科夫链。从中间的状态A 出发,可以分别以等概率0.5
到达B 或C。而从B 或C 出发,都会以概率1 到达A。该马尔科夫链的转移概率矩阵为:
这里写图片描述

马尔科夫链的状态概率分布可以看成一个概率向量(probability vector),其中的每个元素都在[0,1]之间,并且所有的元素之和为1。如果一个N 维的概率向量的每个分量对应马尔科夫链中的一个状态的话,那么该向量就可以被看成是在状态上的一个概率分布。在21-2 给出的简单例子中,概率向量包含3 个总和为1 的元素。

我们可以将Web图上的一个随机冲浪过程看成是马尔科夫链,其中马尔科夫链中的每个状
态对应一个网页,而每个转移概率代表从一个网页跳转到另外一个网页的概率。teleport操作对
这些转移概率的计算具有贡献。Web图的邻接矩阵A可以如下定义:如果存在网页i到网页j的一
条链接,那么Aij=1,否则 Aij=0。这样,我们很容易就可以从N×N的矩阵A推导出马尔科夫链的
转移概率矩阵P。如果A的某一行没有1,则用1/N代替每个元素。对于其他行的处理如下:

(1) 用每行中的1 的个数去除每个1,因此如果某行有3 个1,则每个1 用1/3 代替;
(2) 上面处理后的结果矩阵乘以1−α;
(3) 对上面得到的矩阵中的每个元素都加上α/N。

这样,我们就可以通过概率向量xr 给出冲浪者在任一时间所处位置的概率分布。当t=0 时,冲浪者可能处于某个初始状态,这时xr 中相应的元素为1,其他元素均为0。根据上述定义,在t=1 时,冲浪者的状态分布可以用概率向量这里写图片描述来表示。同样,t=2 时概率向量为这里写图片描述 ,可以依此一直类推下去。这样我们只需状态分布和转移概率矩阵P,就能计算冲浪者在任一时刻所处状态的概率分布。

如果马尔科夫链被允许运行很多次,那么每个状态将会以不同的频率被访问,这个频率依赖于马尔科夫链的结构。在我们的运行模拟中,冲浪者访问某些网页(比如流行的新闻主页)会比其他网页更频繁。下面,我们将这种直观精确化,并建立访问频率收敛于固定的、稳态量的条件。然后,我们将PageRank 设置为每个节点v 在稳态下的访问频率,并介绍它的计算过程。


PageRank 的计算
转移概率矩阵P 的N 维左特征向量这里写图片描述满足:这里写图片描述
主特征向量这里写图片描述是带随机跳转操作的随机游走过程的稳态概率,因此也就是所有WebPage网页的Rank 值。对于公式(21-2)可以采用如下解释:如果这里写图片描述 是冲浪者在网页间的概率分布,那么他会保持在这个稳态概率分布这里写图片描述 中。给定稳态概率分布为这里写图片描述的情况下,有πP=1π,于是1 是P 的一个特征值。所以,如果我们计算出对应于矩阵P 的特征值1 的主左特征向量的话,那么就计算出了PageRank 的值。

这里我们只给出一个非常基本的方法,有时这个方法被称为幂迭代法(power iteration)。
如果这里写图片描述 是初始状态分布向量,那么时刻t的状态分布为这里写图片描述 。当t不断增大时,我们期望这里写图片描述这里写图片描述
非常相近①。当t很大时,我们期望马尔科夫链达到了稳态。根据定理21-1,最后的稳态
布于初始状态分布这里写图片描述 无关。幂迭代方法模拟了冲浪者的游走过程:从某个状态出发,游走一个很大的步数t,并跟踪对每个状态的访问频率。在经过一个很大步数t之后,这些频率会稳定下来,此时计算得到的访问频率的变化值会低于某个预先定义的阈值。这些访问频率就是我们要计算的PageRank值。
考虑以下web图,其中α=0.5。
这里写图片描述
于是,冲浪者带随机跳转操作的随机游走过程的转移概率矩阵为:
这里写图片描述
设想冲浪者的初始状态为1,对应的初始状态概率分布向量为这里写图片描述。于是,一步之后的概率分布为:
这里写图片描述

反复迭代一定次数之后,我们会看到分布收敛于一个稳定状态这里写图片描述 。在这个简单的例子中,我们注意到(21-3)式中的转移概率矩阵的第一行和第三行是相等的,也就是说该马尔科夫链中状态1 和状态3 具有对称性,于是可以直接计算稳态的概率分布。假定状态1 和状态3 具有相同的稳态概率, 记为p , 则最后的稳态概率分布的形式为这里写图片描述。现在,利用恒等式这里写图片描述 ,我们就可以求解一个简单的线性方程,从而得到p = 5/18,于是π = (5 /18 4 / 9 5 /18)。


一个简单的例子:
考虑以下的web图,其中随机跳转操作的概率是0.14
这里写图片描述
于是,冲浪者带随机跳转操作的随机游走过程的转移概率矩阵为:
这里写图片描述

代码如下:


package test6;import java.math.BigDecimal;public class pageRank {    public static void main(String[] args){         //初始化原始矩阵         double[][] matrix ={                          {0,0,1,0,0,0,0},                  {0,1,1,0,0,0,0},                  {1,0,1,1,0,0,0},                  {0,0,0,1,1,0,0},                  {0,0,0,0,0,0,1},                {0,0,0,0,0,1,1},                {0,0,0,1,1,0,1},         };         double [][] TransitionMatrix;         TransitionMatrix=getTransitionMatrix(matrix);          //获得转移概率矩阵         System.out.println("转移概率矩阵为:");         for(int i=0;i<TransitionMatrix.length;i++){             for(int j=0;j<TransitionMatrix[0].length;j++){                 System.out.print(TransitionMatrix[i][j]);                 System.out.print(" ");             }             System.out.println();         }         //设想冲浪者的初始状态为1,对应的初始状态概率分布向量为arrayPR,即意味着从网点1开始冲浪         double[] arrayPR={1,0,0,0,0,0,0};           double[] pageRank=getPageRank(arrayPR, TransitionMatrix);    //获得pageRank         System.out.println("该矩阵的PageRank向量为:");         for(int i=0;i<pageRank.length;i++){             System.out.print(pageRank[i]+" ");         }    }    public static double[][] getTransitionMatrix(double[][] matrix){               //获得转移概率矩阵        double [][] TransitionMatrix;        TransitionMatrix=matrix;        int rowLength=matrix.length;//行长度        int colLength=matrix[0].length;//列长度。        double α=0.14;      //假定随机跳转操作的概率是0.14,这是个可变的常数        int i,j;        int count=0;        for(i=0;i<rowLength;i++){         for(j=0;j<colLength;j++){             if(TransitionMatrix[i][j]==1){      //如果两点之间为1表示这两点之间有通路                count++;                         //计算出有该网点与多少个网点有通路             }         }         if(count==0){                           //如果该网点是个孤岛,与任一网点无通路            for(j=0;j<colLength;j++){                double number=1.0d/colLength;                       TransitionMatrix[i][j]=number;      //则连通所有网点            }         }else{                                 //如果该网点不是孤岛            for(j=0;j<colLength;j++){                if(TransitionMatrix[i][j]==1){                    double number=1.0d/count;                    TransitionMatrix[i][j]=number;                }            }          }         count=0;        }        //矩阵乘以1−α;           //每个元素都加上α/N。         for(i=0;i<rowLength;i++){             for(j=0;j<colLength;j++){                TransitionMatrix[i][j]*=1-α;                TransitionMatrix[i][j]+=α/rowLength;                 }         }        //保留两位小数         for(i=0;i<rowLength;i++){             for(j=0;j<colLength;j++){                 double n=matrix[i][j];                 BigDecimal b=new BigDecimal(n);                   double n1=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();                   TransitionMatrix[i][j]=n1;             }         }              return TransitionMatrix;     //返回转移概率矩阵    }    //计算一个矩阵乘以一个向量    public static double[] vectorMulMatrix(double[] arrayPR,double[][] TransitionMatrix){        double[] pageRank =new double[arrayPR.length];          for(int i=0;i<TransitionMatrix.length;i++){            double sum = 0;            for(int j=0;j<TransitionMatrix[i].length;j++){                double temp=TransitionMatrix[j][i]*arrayPR[j];                  sum+=temp;            }             BigDecimal b=new BigDecimal(sum);               double n=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();    //保留两位小数            pageRank[i]=n;        }        return pageRank;    }    //计算两个向量的距离    public static double calDistance(double[] q1,double[] q2) {          double sum = 0;          if (q1.length!=q2.length) {              return -1;          }          for (int i = 0; i < q1.length; i++) {              sum += Math.pow(q1[i]-q2[i],2);          }          return Math.sqrt(sum);      }      //计算pageRank    public static double[] getPageRank(double[] arrayPR,double[][] TransitionMatrix){        double[] pageRank=new double[arrayPR.length];        int time=0;           //迭代次数        while(true){                                             //反复迭代直到收敛            pageRank=vectorMulMatrix(arrayPR, TransitionMatrix);                time++;            double dis=calDistance(pageRank, arrayPR);           //计算两向量的距离            if(dis==0){                                          //向量之间的距离不变时,认为已经收敛,退出迭代                break;            }               arrayPR=pageRank;                                    //将arrayPR赋值为上一个pageRank        }        System.out.println("迭代次数为:"+time);        return pageRank;                                         //返回pageRank    }}

结果如下:
这里写图片描述

最后会稳定在 0.05 0.03 0.11 0.25 0.21 0.03 0.3
所以该web图的PageRank即为 0.05 0.03 0.11 0.25 0.21 0.03 0.3