随机游走的PageRank算法 sensitive PageRank

随机游走的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的概率向邻居节点转移。

     随机游走的PageRank算法 sensitive PageRank_第1张图片

所以,我们在转移过程中。转变H矩阵为Htem矩阵。

         所以我们可以

 

这里的Htem取代原来的H,now的意思就是从now节点开始出发进行计算的节点,因为有alpha的概率返回到now节点(聪明的你一定能够知道,随机游走不过就是让每个节点有alpha的概率返回到最初的now节点嘛)

         这里附上一个非矩阵实现的代码,实现方式有很多,你们可以用其他方式实现;

 

根据这个递推,这个公式,和PageRank算法一样,最终结果会收敛,收敛的判定依据在上面的算法中可以看到,是sampleCorrelationCoefficient,其实就是一个相关系数或者你自己定义其它的距离如欧式距离等,不过上面用例中用的是皮尔逊相关系数,并且每循环100000次,再检查,这是由于皮尔逊相关系数的性质决定的,针对不同情况,这里是可以改变的。

         因为过程中alpha的概率返回源节点,所以从不同的节点出发,会有不同的结果,上面的例子中你可以看到是一个节点一个节点进行rank值的转移,如果我们使用矩阵的方式进行转移呢?其实就是初始化的时候,出发节点的rank值为1,其它为0就可以了。

 


你可能感兴趣的:(算法,search,pagerank,sensitive,随机游走)