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
- PageRank计算方法(通过power iteration方式来实现)
- PageRank计算方法的SQL实现
- PageRank计算方法及java实现
- PageRank计算方法及java实现
- Power iteration clustering (PIC)
- Spark MLlib 中power iteration clustering (PIC)算法简介
- 使用MapReduce来实现PageRank算法
- PageRank算法(python实现)
- AOP实现方式3——通过<aop:config>来配置(纯POJO切面)
- AOP实现方式3——通过<aop:config>来配置(纯POJO切面)
- Spring 通过Spring AOP 方式来实现AOP
- 通过继承来实现注解方式的属性注入
- 通过经典题目来理解多种闭包实现方式
- 用Httpclient通过post方式来实现http请求
- 将HystrixCommand通过Observable来实现响应式执行方式
- 实现pageRank
- PageRank的简单实现(scala版)
- Matlab实现——Jacobi Iteration and Gauss-Seidel Iteration
- Mac安装Mongodb
- 5种排序算法的c#代码(1)
- React-Native进阶_1.抽取样式和组件
- nm: test.o: File format not recognized的原因和解决方案
- 配置JAVA的环境变量
- PageRank计算方法(通过power iteration方式来实现)
- 2017 Multi-University Training Contest
- React-Native进阶_2.加载指示动画 ActivityIndicator
- React-Native进阶_3.触摸高亮显示TouchableHighlight
- Redis--(linux安装redis3.2.9主从复制与集群的搭建--教程)
- 软件
- IO字节流,OutputStream和InputStream
- 5种排序算法的js代码(1)
- 如何用OpenCV训练自己的分类器