一、写在前面
本文是《统计学习方法》第二十一章PageRank读书笔记。《方法》从第十四章起开始涉及无监督学习,而个人发现无监督学习的作用和性能相比监督学习都很有限。拿众所周知的聚类来说,在业务或者数据处理的过程中,其作用还是较为有限的,笔者对其的应用能力尚不足。因此决定对这一部分无监督学习不再续更。然而PageRank不仅在搜索引擎中得到广泛应用,还在影响力分析、文本分析等领域大放异彩,因此有必要详细了解每一处细节。本文作个人备忘用,不保证质量和延续性。
二、PageRank的定义
2.1 基本想法
历史上,PageRank算法作为计算互联网网页重要度的算法被提出。PageRank是定义在网页集合上的一个函数,它对每个网页给出一个正实数,表示网页的重要程度,整体构成一个向量。PageRank的值越高,网页就越重要,在互联网搜索的排序可能就被排在前面。
直观上,一个网页,如果指向该网页的超链接越多,随机跳转到该网页的概率也越高,该网页的PageRank的值就越高,这个网页也就越重要。同时,如果指向一个网页的PageRank越高,随机跳转到该网页的概率也就越高,该网页的PageRank值就越高。
PageRank的计算可以在互联网的有向图上进行,通常是一个迭代过程。先假设一个初始分布,通过迭代,不断计算所有网页的PageRank值,直到收敛为止。
2.2 模型抽象
将网页抽象中图中的一个节点,网页之间的链接关系表示一条有向边,整个web被抽象成一个有向图。如下图;
个例子中只有四个网页,如果当前在A网页,那么悠闲的上网者将会各以1/3的概率跳转到B、C、D,这里的3表示A有3条出链,如果一个网页有k条出链,那么跳转任意一个出链上的概率是1/k,同理D到B、C的概率各为1/2,而B到C的概率为0。
我们在做计算的时候会将该图表示成一个二维的矩阵,我们做一个转换,就会变成下图的矩阵形式。M[i,j]表示j节点指向i节点的概率 ,一般来说每列和为1。
M为转移概率矩阵,随机游走在某个时刻
t
t
t访问各个结点的概率分布就是马尔科夫链在时刻
t
t
t的状态分布,可以用一个n维列向量
R
t
R_t
Rt表示,那么在时刻
t
+
1
t+1
t+1访问各个结点的概率分布
R
t
+
1
R_{t+1}
Rt+1满足:
R
t
+
1
=
M
R
t
R_{t+1}=MR_t
Rt+1=MRt
2.3迭代计算
那么PageRank是怎么求出来的?
在算法的第一轮计算中,我们假设上网者在每一个网页的概率都是相等的,即1/n,于是初试的概率分布就是一个所有值都为1/n的n维列向量
V
0
V_0
V0,用
V
0
V_0
V0去右乘转移矩阵
M
M
M,就得到了第一步之后上网者的概率分布向量
M
V
0
MV_0
MV0。(nXn)(nX1)依然得到一个nX1的矩阵
V
1
V_1
V1,这个
V
1
V_1
V1就是一轮迭代计算出来的PageRank值。下面是
V
1
V_1
V1的计算过程:
得到了
V
1
V_1
V1后,再用
V
1
V_1
V1去右乘
M
M
M得到
V
2
V_2
V2,一直下去,最终
V
V
V会收敛,即
V
n
=
M
V
n
−
1
V_n=MV_{n-1}
Vn=MVn−1,上面的图示例,不断的迭代,最终
V
V
V=[3/9,2/9,2/9,2/9]:
三、Dead Ends 问题
3.1 问题引出
一般的有向图未必满足强连通且非周期性的条件。比如,在互联网,大部分网页没有连接出去的超链接,也就是说从这些网页无法跳转到其他网页。所以PageRank的基本定义不适用。
有兴趣的读者可以将上述图中结点
C
C
C到结点
A
A
A的路径去除,此时表示网页C没有连接出去的超链接。由此,相应的
M
M
M矩阵中的第三列则变为全0。此时继续连乘向量
R
R
R,最终的极限会是
V
V
V=[0,0,0,0]。可见,随着时间的推移,访问各个节点的概率皆为0。
因此引出了PageRank的一般定义
互联网浏览者按照以下方法在网上随机游走:在任意一个网页上,浏览者或者以概率
d
d
d决定按照超链接随机跳转,这时以等概率从连接出去的超链接跳转到下一个网页;或者以
(
1
−
d
)
(1-d)
(1−d)的概率决定完全随机跳转。这时以等概率1/n跳转到任意一个网页。第二个机制保证从没有连接出去的超链接的网页也可以跳转出去。这样可以保证平稳分布,即一般PageRank的存在,因而一般PageRank适用于任意网络结构。
3.2 迭代算法
具体地,给定一个含有n个结点的有向图,转移矩阵为M,有向图的一般PageRank迭代公式为:
R
t
+
1
=
d
M
R
t
+
(
1
−
d
)
/
n
∗
1
R_{t+1}=dMR_t+(1-d)/n*1
Rt+1=dMRt+(1−d)/n∗1,其中d一般取0.8,模拟从连接出去的超链跳转到下个网页的概率,
1
1
1为元素全为1的向量。
算法流程:
输入:含有n个结点的有向图,转移矩阵
M
M
M,阻尼因子
d
d
d,初始向量
R
0
R_0
R0;
输出:有向图的PageRank向量
R
R
R。
(1)令t=0
(2)计算
R
t
+
1
=
d
M
R
t
+
(
1
−
d
)
/
n
∗
1
R_{t+1}=dMR_t+(1-d)/n*1
Rt+1=dMRt+(1−d)/n∗1
(3)如果
R
t
+
1
R_{t+1}
Rt+1与
R
t
R_t
Rt充分接近,令
R
=
R
t
+
1
R=R_{t+1}
R=Rt+1,停止迭代。
(4)否则,令t=t+1,执行步骤(2)
四、python实现
from numpy import *
def graphMove(a):#构造转移矩阵,其实就是把每一列的值的和归一化得到转移概率矩阵,很容易理解
b=transpose(a)
c=zeros((a.shape),dtype=float)
for i in range(a.shape[0]):
for j in range(a.shape[1]):
c[i][j]=a[i][j]/(b[j].sum())
return c
def firstPr(c):
pr=zeros((c.shape[0],1),dtype=float)
for i in range(len(c)):
pr[i]=float(1)/len(c)
return pr
def PageRank(d,c,pr,con_rate):#参数分别为阻尼系数、转移概率矩阵、初始向量和收敛约束因子
while abs((pr-((d*dot(c,pr)+(1-d)*pr))).sum())>con_rate:
pr=d*dot(c,pr)+(1-d)*pr
return pr
a=array([[0.0,1.0,1.0,0.0],
[1.0,0.0,0.0,1.0],
[1.0,0.0,0.0,1.0],
[1.0,1.0,0.0,0.0]])
c=graphMove(a)
pr=firstPr(c)
print(PageRank(0.80,c,pr,0))
其中关键函数PageRank的参数分别为阻尼系数、转移概率矩阵、初始向量和收敛约束因子。收敛约束因子是指,当新一轮迭代产生的向量与上一轮的向量的差距已经小于收敛约束因子时,停止迭代。在本例中,将收敛因子设置成0则表示迭代需要达到完全收敛,新的向量完全等于上一轮向量时,才停止迭代。
PageRank算法实现起来极为简洁,可谓平易近人而又功能强大的好算法。当然这只是四个结点的情况。当矩阵更大,或许就不是那么容易的事了。但万变不离其宗,原理和实现便是如此。