随机游走的pagerank建立在pagerank基础之上,
PageRank的简单介绍请看这里http://blog.csdn.net/zhonghuan1992/article/details/24396435
请先看随机游走的pageRank算法部分代码(代码写的挫了写见谅),根据代码分析
#include <cstdio> #include <cstring> #include <cmath> #include <cstring> #include <vector> #include <ctime> #include <cstdlib> using namespace std; const int m=3000; const double alpha=0.25; vector<int> neighbor[m];//这里的neighbor存的是每个节点的相邻节点 vector<int * > ans;//存的是答案 int * rank; int * oldRank; // FILE *fp1,*fp2; //返回平均值 double mean(int * tem) { double ans=0; for(int i=0;i< m;i++) ans+=tem[i]; return ans/m; } //返回样例的标准差 double standardDeviation(int * tem,double xmean) { double sum = 0; for( int i = 0; i < m; i++ ) { sum += pow( tem[i] - xmean, 2 ); } return sqrt( sum / (m-1) ); } //计算相关系数 double sampleCorrelationCoefficient(int * oldrank,int * rank) { double xmean = mean(rank); double ymean = mean(oldrank); double xStdDev = standardDeviation(rank,xmean); double yStdDev = standardDeviation(oldrank,ymean); double sum = 0; for( int i = 0; i < m; i++ ) { sum += (rank[i]-xmean) * (oldrank[i]-ymean); } return sum /((m-1) * xStdDev * yStdDev); } //返回一个新的int数组 int* rankMake() { int * temp=new int[m]; for(int i=0;i<m;i++) temp[i]=0; return temp; } //这里勿喷,只是为了让rank复制给oldrank void copy() { for(int i=0;i<m;i++) oldRank[i]=rank[i]; } void init() { for(int i=0;i<m;i++) neighbor[i].clear(); int x,y; //读取数据,数据的格式就是x和y,表示x关注了y while(scanf("%d %d",&x,&y)!=EOF) { neighbor[x].push_back(y); } } int main() { init(); //循环为每一个节点计算针对该节点的所有节点rank for (int i = 0; i < m; i++) { rank=rankMake(); oldRank=rankMake(); int vertex=i; int currentVertex=vertex; for(int step = 1; true; step++ ) { //每10000次才比较,主要是因为本文相关系数的关系,可以不用本文的相关系数,可以自己修改 if( neighbor[currentVertex].size() < 1 || (double)rand()/RAND_MAX < alpha ) { currentVertex=vertex; } else { int randomNeighbor = rand() % neighbor[currentVertex].size(); currentVertex = neighbor[currentVertex][randomNeighbor]; } rank[currentVertex]++; if( step == 100000 ) { copy(); } else if( step % 100000 == 0 ) { double r = sampleCorrelationCoefficient( oldRank, rank ); if( r > 0.9999 ) //这里控制精度,如果你是精度控,那么,可以写0.999999999999,当然这里主要是因为 break;//相关系数的原因,0一点不相关,1及其相关,我们当然是觉得越相关越好 else copy(); } } ans.push_back(rank); printf("%d的邻居的rank:\n",i); for(int j=0;j<neighbor[i].size();j++) { printf(" (%d:%d) ",neighbor[i][j],rank[neighbor[i][j]]); } printf("\n"); } return 0; }
在遍历的过程中,有alpha的概率返回原节点,有1-alpha的概率向邻居节点转移。
所以,我们在转移过程中。转变H矩阵为Htem矩阵。
所以我们可以
这里的Htem取代原来的H,now的意思就是从now节点开始出发进行计算的节点,因为有alpha的概率返回到now节点(聪明的你一定能够知道,随机游走不过就是让每个节点有alpha的概率返回到最初的now节点嘛)
这里附上一个非矩阵实现的代码,实现方式有很多,你们可以用其他方式实现;
根据这个递推,这个公式,和PageRank算法一样,最终结果会收敛,收敛的判定依据在上面的算法中可以看到,是sampleCorrelationCoefficient,其实就是一个相关系数或者你自己定义其它的距离如欧式距离等,不过上面用例中用的是皮尔逊相关系数,并且每循环100000次,再检查,这是由于皮尔逊相关系数的性质决定的,针对不同情况,这里是可以改变的。
因为过程中alpha的概率返回源节点,所以从不同的节点出发,会有不同的结果,上面的例子中你可以看到是一个节点一个节点进行rank值的转移,如果我们使用矩阵的方式进行转移呢?其实就是初始化的时候,出发节点的rank值为1,其它为0就可以了。