pagerank其实是搜索引擎的一个步骤,
搜索引擎要做起来,
1 需要网页数据集作为数据源
2 需要比较合适的数据结构方便检索存储
3 需要一个比较合适的算法将检索到的数据集进行排序展现给大众。
pagerank其实就是第三件事情,
实质上是一个资源的流动配置的方法
所谓的“资源”在这里可以理解为名声和信用,牛逼的网站只引用更加牛逼的网站,这是对所引用网站的一种认可的表现
我们假定名声资源是一定的
1) 资源矩阵V:为各个网页的初始化的名声资源,总和一定。其实就是PageRank的结果(V缩写取自Value)
2) 分配矩阵M:有一个资源配置的矩阵M负责资源的具体分配(M缩写取自Manage管理)
3) 有了上面两项,我们开始利用M矩阵,不断的进行V=MV操作,对名声资源矩阵进行迭代更新计运算。
V=initial_val
while((MV-V)
通过V'=MV 不断进行V的流动配置,V不断的更新,直到V名声资源差不多稳定的时候就说可以了
既然大家对资源的争名夺利倒腾的差不多了,诸侯都默认了各自的统治权了,V就基本不变了,那么就开始分封rank吧。
然后大家就按照名声资源稳定的程度进行排序,这个顺序就是Google输出的顺序了
需要再次强调PageRank的几个根本上的假定
假定1 假定资源是一定的,这样分配才有意义,不然就不叫分配了,大家可以自产自销
假定2 假定这个拓扑网络体系是流动的,整个路径都是贯通的,最典型的就是资源能够从一个点出发,跑到这个网络上的任意一个地方,然后又有能力活着跑回来。这样才叫流动,只有流动才到最后有收敛有均衡有稳定。
反例就是Rank Sink 或者Dangling Link: 只接收不输出 就是特别吊的网站,都是人家引用他的,对他的名声进行肯定。而没有他引用其他网页,因此名声资源到了该网站,无法流向其他地方。这种情况会造成迭代过程最终无法收敛,资源全部集中到这样的牛逼网站节点,而其他地方资源为0。
Rank Sink可以是一个很diao的网站,也可以是一组很diao的网站,他们之间相互引用,搞自己的小循环,而外人只有引用他们的份。
这个问题如何解决?难道大家通过一个一个连接访问到这么吊的网页,就高山仰止,不看其他网页了么?不是的,也许他们会很随机的访问其他的网页找个其他的东西,也就是说当我们遇到这种情况的时候,我们就默认将这种比较吊的网页的名声资源平均分散到其他的网页中,每个网页都分了一杯羹,这样保证了名声资源到了Sink网页节点还能够继续的流动,从而保证名声资源网的连通性。
假定3 整个网页资源的pageRank值最终稳定的和初始值没有关系。这个是markov随机模型的特性。
我个人认为PageRank其实不是Rank排序,而是一种资源配置方式,配置好之后,再根据资源大小进行排序输出。论文的“正向链接”,其实就是引用,代表着一种给予名声资源的操作,是在输出资源的操作. 相反,在另一方看来,反向链接就是接收资源的操作了。
PageRank通过V'=MV 不断进行V的流动配置,V不断的更新,直到V名声资源差不多稳定的时候就说可以了
既然大家对资源的争名夺利倒腾的差不多了,诸侯都默认了各自的统治权了,边界基本清楚了,就开始分封rank吧。
默认的迭代的矩阵是M,其中c是常数值 R=cMR
但是考虑到dangling link的情况,需要添加跳出情况。 R = cMR +cE = c( MR+E )=c(CM+E*1)=cKR
化简后,R就是矩阵K的特征向量
1 可以通过迭代计算R和R‘之间的误差到底差多少? 降到一定阈值,则说明收敛。
2 可以直接从线性代数考虑,式子可以写成, (1/c)R=KR, 那么所求的矩阵R其实就是矩阵K的特征向量,而1/c就是特征值
通过计算求的矩阵K,K的最大特征值所对应的特征向量(其实就是主特征向量),就是pagerank结果R了
方法1的实现-------------------------------------------------
参考https://gist.github.com/diogojc/1338222
import numpy as np
from scipy.sparse import csc_matrix #稀疏矩阵库函数
def pageRank(G, s = .85, maxerr = .001):
n = G.shape[0]
# 邻接矩阵的稀疏矩阵
M = csc_matrix(G,dtype=np.float)
#计算概率分布矩阵
rsums = np.array(M.sum(1))[:,0]
ri, ci = M.nonzero()
M.data /= rsums[ri]
#迭代计算PageRank值
ro, r = np.zeros(n), np.ones(n)
while np.sum(np.abs(r-ro)) > maxerr: #收敛判断阈值
ro = r.copy()
for i in range(0,n):
Mi = np.array(M[:,i].todense())[:,0] #分布矩阵的列
Ei = np.ones(n) / float(n) #随机分布矩阵的列
r[i] = ro.dot( Mi*s + Ei*(1-s) ) #s为转移概率
#结果归一化返回
return r/sum(r)
def run():
G = np.array([ [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]])
print pageRank(G,s=.86)