PageRank算法实现好友推荐(算法原理)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PageRank算法实现好友推荐(算法原理)相关的知识,希望对你有一定的参考价值。
参考技术A对于社交系统与电商网站,推荐系统占有很重要的位置,当数据量越来越大的时候,用户无法确定该选择什么商品,因此在电商系统中需要按照兴趣或者相似度给用户推荐相应的商品。相应的,在一个大型社交网络平台中,对于一些用户,我们希望推荐一些知名度较高,活跃度较高或者感兴趣的用户,比如一些明星,歌手,演员等等。在社交网络中,PageRank算法有着广泛的应用,因此,本篇文章主要介绍其原理。
对于大部分社交系统来说,如果只是简单的获取好友的信息远远不够,我们可以通过获取好友的好友的信息来扩展用户的朋友圈,使得信息量更加丰富,本项目中使用PageRank算法来完成二级邻居,然后按照Rank排序,选择Top5用户实现用户的好友的好友的推荐。
PageRank算法由Google的创始人拉里·佩奇和谢尔·布林于1998年发明.这项技术设计之初是为了体现网页的相关性和重要性,在搜索引擎优化操作中经常被用来评估网页优化的成效因素之一.
从技术上看,搜索引擎需要解决以下三个问题:
本质就是一个爬虫问题,通过爬虫获取整个互联网的数据
关键在于快速找到.
它的实现方式有: 倒排索引,签名文件,后缀树等。我们最熟悉的是 倒排索引 。(并不熟悉,以后有机会再看)
排序是Google的搜索引擎能够兴起的一个决定性因素。
对网页排序有很多种方式,我们来看三种:
就是原封不懂地把索引到的链接直接返回给用户,缺点就不说了,想找自己感兴趣的内容估计要费不少功夫。
这种方式是一种只从关键词出现的次数和位置进行排序的方法。该方法以一个关键词与网页的相关度大小作为排序标准,而关键词在网页的相关度大小作为排序标准,而关键词在网页中的相关度则由它在网页中出现的频次和位置两方面加权计算得出。
缺点也很明显,容易出现刷分的情况,整篇文章中大量地刷关键词就能提高排名。
真正找到计算网页自身质量的完美的数学模型是Google的创始人拉里佩奇和谢尔盖布林。 下一节讲一下原理。
我们模拟一个悠闲的上网者,上网者首先随机选择一个网页打开,然后在这个网页上呆了几分钟后,跳转到该网页所指向的链接,这样无所事事、漫无目的地在网页上跳来跳去,PageRank就是估计这个悠闲的上网者分布在各个网页上的概率,这个概率就代表这个网页的重要性.
PageRank主要基于两个重要的假设:
如果一篇文章被越来越多的人引用,那么这篇文章可能就是一篇经典之作,如果这篇文章引用了其他的论文,那么一定程度上这篇被引用的文章也是一篇很好的文章。应用到社交网络中,如果一个好友被更多的人关注,那么说明该好友有很高的知名度和活跃度,那么,我们可以将该好友推荐给用户。
基于这两个假设,我们可以总结出PageRank算法的核心:
如下图,可以更好的表达PageRank算法的思想:
由上图可知,每个页面将自己的一部分rank传递给某个页面,我们可以通过计算传递给某个页面的所有rank值的和来计算出它的rank值,当然,不可能是通过一次计算完成,我们刚开始可以给每个页面赋予一个初始rank值,比如 1/N(N为页面总数) ,通过迭代计算得到该页面的rank值。
迭代计算停止的条件为:
使用有向图表示:
这个例子中只有四个网页,如果当前在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。
生成的 转移矩阵 非常简单, 矩阵的每一列代表该顶点所代表的页面除以对应页面的出链数得到的 。
有了转移矩阵,我们可以来定义行向量 V , V 的第i个分量记录 对应的Rank值,因此一次Rank的更新可以表示为:
在算法的第一轮计算中,我们假设上网者在每一个网页的概率都是相等的,即1/n,于是初试的概率分布就是一个所有值都为1/n的n维列向量 ,用 去右乘转移矩阵M,就得到了第一步之后上网者的概率分布向量 ,得到一个nX1的矩阵 , 这个 一轮迭代计算出来的PageRank值 。下面是 的计算过程:
得到了 后,再用 去右乘M得到 ,一直下去,即 , 最终V会收敛 .
不断的迭代,最终得到结果.
但是在迭代计算中,我们需要考虑如下两大阻力: Dead End 和 Spider Trap :
Dead End就是指一个页面只有入链但是没有出链,这时转移矩阵M的一列为零,导致最后结果为零。这时web不是强连通的,即存在某一类节点不指向别人,如下图的D。这个时候我们的算法就会出问题了,它不满足收敛性了。
为什么不满足收敛性了?
Spider Trap指页面的所有出链都指向自己,这样会使迭代结果中只有自己的页面的Rank值很高。其他页面的Rank值为零。
要克服上面两个问题,我们需要将迭代计算公式做如下转变。我们可以加入一个 随机跳转 机制.
即假设每个页面有很小概率拥有一个指向其他页面的链接。
表现出来就是:其他页面本来传递给一个页面的Rank值需要做一个折扣,作为补偿,可能需要一个页面指向该页面并且传递Rank值给该页面,该跳转的概率为β,因此表达式变为:
其中,N为页面总数; e 为一个N维且各个分量都是1的向量;β通过经验得知一般设为0.15.
此时的计算结果过程为:
有机会再写,先空着
PageRank算法原理与Python实现
PageRank算法原理与Python实现
参考
.PageRank算法--从原理到实现
零. PageRank算法简介
PageRank算法,即网页排名算法,由Google创始人Larry Page在斯坦福上学的时候提出来的。该算法用于对网页进行排名,排名高的网页表示该网页被访问的概率高。
该算法的主要思想有两点:
a. 如果多个网页指向某个网页A,则网页A的排名较高。
b. 如果排名高A的网页指向某个网页B,则网页B的排名也较高,即网页B的排名受指向其的网页的排名的影响。
一、PageRank算法原理
1. 简单的PageRank算法
如图是一个4个网页之间的链接情况:
假设网页X的排名用PR(X)表示,则A的排名为PR(A),由图可知,网页B和C指向了网页A,那么网页A的排名可以表示为:
网页C只指向了A,不指向其他网页,然而网页B不仅指向了A,还指向了D,因此上面的公式更合理地修改为:
意思是,B的PageRank值被分给了A和D,而C的PageRank值全都给了A。
2. 考虑没有出边(outlink)的网页
有的网页,没有指向其他网页,如下图中的C网页。
那么,假设网页C的PageRank值被均分为到图中的所有网页(4个网页),那么A网页的PageRank值可以表示为:
3. 网页链接中存在环
图中网页C指向网页C,不指向其他网页。现实中,网页自己指向自己的情况可能不太常见,但是有可能的情况是:若干个页面形成一个环,那么用户在进入其中某个网页的时候,就陷入这个循环中。
假设当一个用户,遇上这种情况时,以某个概率α随机指向其他任意一个网页,每个网页的概率相等。因此上图中的网页A的PageRank值可以表示为:
上面这个公式可以解释为:α表示用户从网页B以概率α链接到网页A,后面的(1-α)表示用户从网页C以概率(1-α)链接到网页A。
即:
网页B的PageRank值分配情况为:α*1/2给A, α*1/2给D,(1-α)/4分别给4个网页。
网页C的PageRank值分配情况为:α*1给自己C(1-α)*1/4分别给其他网页。
4. 更一般的PageRank公式
综合上面的论述,一般的PageRank计算公式为:
其中S(X)表示,指向网页X的所有网页的集合,n_i表示网页Y_i的出边数量,N表示所有网页总数,α一般取0.85。
二、PageRank值的计算方法
1. 迭代法
利用前面得到的公式,进行迭代,直到迭代前后两次的差值在允许的阈值范围内,迭代结束。
当然,可以将迭代过程写成矩阵形式。推导过程如下:
针对前面的最后一个网络图,可以分别得到各个网页的PageRank值得计算公式,如下:
写成矩阵的形式为:
可以将上面的列向量和矩阵分别记为一些符号,上式表示为:
还有更简洁的记法,记
A是一个常数矩阵,那么,就有迭代公式:
也可以根据这个公式,进行迭代。
2. 代数法
因为,PageRank算法最终收敛(这个结论可以证明,此文不证明),因此,收敛时刻的PageRank值组成的列向量P应当满足:
因此有:
这个方法不用迭代,求出矩阵的逆,就可以求出PageRank值组成的列向量P(然而,计算大规模的矩阵的逆,也是个难题。因此,这个方法代码简单,但效率可能不如迭代方法高)
三、Python实现
下面仅仅实现迭代法,代码如下,需要用到Python的numpy库用于矩阵乘法:
# 输入为一个*.txt文件,例如
# A B
# B C
# B A
# ...表示前者指向后者
import numpy as np
if __name__ == '__main__':
# 读入有向图,存储边
f = open('input_1.txt', 'r')
edges = [line.strip('\\n').split(' ') for line in f]
print(edges)
# 根据边获取节点的集合
nodes = []
for edge in edges:
if edge[0] not in nodes:
nodes.append(edge[0])
if edge[1] not in nodes:
nodes.append(edge[1])
print(nodes)
N = len(nodes)
# 将节点符号(字母),映射成阿拉伯数字,便于后面生成A矩阵/S矩阵
i = 0
node_to_num =
for node in nodes:
node_to_num[node] = i
i += 1
for edge in edges:
edge[0] = node_to_num[edge[0]]
edge[1] = node_to_num[edge[1]]
print(edges)
# 生成初步的S矩阵
S = np.zeros([N, N])
for edge in edges:
S[edge[1], edge[0]] = 1
print(S)
# 计算比例:即一个网页对其他网页的PageRank值的贡献,即进行列的归一化处理
for j in range(N):
sum_of_col = sum(S[:,j])
for i in range(N):
S[i, j] /= sum_of_col
print(S)
# 计算矩阵A
alpha = 0.85
A = alpha*S + (1-alpha) / N * np.ones([N, N])
print(A)
# 生成初始的PageRank值,记录在P_n中,P_n和P_n1均用于迭代
P_n = np.ones(N) / N
P_n1 = np.zeros(N)
e = 100000 # 误差初始化
k = 0 # 记录迭代次数
print('loop...')
while e > 0.00000001: # 开始迭代
P_n1 = np.dot(A, P_n) # 迭代公式
e = P_n1-P_n
e = max(map(abs, e)) # 计算误差
P_n = P_n1
k += 1
print('iteration %s:'%str(k), P_n1)
print('final result:', P_n)
输入的input_1.txt文本内容为:
A B
A C
A D
B D
C E
D E
B E
E A
结果为:
最后的一个数组,分别为A, B, C, D, E的PageRank值,其中E最高, A第二高, B和C相同均最低。
我们再来看一下这个可视化的有向图:
可以看出,有3条边指向E。再看,指向A的这个点是E点,因此A的PageRank值也很高,可以说“A沾了E的光”。
上面的可视化代码如下:
import networkx as nx
import matplotlib.pyplot as plt
if __name__ == '__main__':
# 读入有向图,存储边
f = open('input_1.txt', 'r')
edges = [line.strip('\\n').split(' ') for line in f]
G = nx.DiGraph()
for edge in edges:
G.add_edge(edge[0], edge[1])
nx.draw(G, with_labels=True)
plt.show()
以上是关于PageRank算法实现好友推荐(算法原理)的主要内容,如果未能解决你的问题,请参考以下文章