如果我们自己做搜索,我们可以想到的是文章和搜索词之间的相关性,从而判断这篇文章是不是我们想要的。一些初期的搜索都是这样,根据网站的类型也有很大的索引表,但是能索引的关键词是有限的。Internet上估计有数千亿个网页(猜测),因此显然并非所有包含搜索关键字的网页都同等重要。有的在标题中包含关键词,有的在文档中包含关键词;有的是权威机构网站,有的是个人博客。显然,在给用户返回网页的时候,比较重要的网页应该排在前面,不重要的网页应该排在前面。接下来是信息。那么还有一个问题,如何判断一个网页的重要性。网页是由链接组织的,所以我们可以把整个互联网看成一个大图,每个节点就是一个网页,网页之间的链接被看做是边。一个网页是否重要取决于是否有多个网页链接到它。由更多网页链接的网页更重要。当然,链接到该网页的多个链接的重要性是不同的。假设我们从搜索中得到很多网页,一个网页Y的排名应该来自指向这个网页X1,X2,X3的所有权重之和:Y网页的权重=X1+X2+X3。..+Xn和X1,X2,...Xn的权重是多少以及如何测量它们?这需要通过链接到它的网页的权重来计算。这样一来,无解。据说谷歌的布林打破了这个恶性循环,就是一开始给每个网页设置相同的初始值,然后经过多轮计算,这个算法可以保证网页的排名会收敛到真实值多次后的排名。据我了解,大致是这样的:第一轮,我们假设所有网页的权重都是1,那么A的网页的权重是1+1+1,也就是3。在第二轮计算,同A相连的网页权重变为2,最后A网页的权重变为2+2+2=6。经过多次计算,权重高的网页越多链接的网页排名靠前,另一个靠后。整个过程有点类似于民主选举,每个人的选票在选举过程中的权重都不一样,这也和现实很相似。那么PageRank算法除了计算网页排名还有什么用呢?在《数据实战》第45讲中,有个例子比较有意思。它计算人物对泄露的希拉里邮件列表的影响。通过python的networkx库可以很方便的计算出PageRank。价值。以下网络图:计算PageRank的简单代码:importnetworkxasnx#创建有向图G=nx.DiGraph()#有向图之间的边关系edges=[("B1","B"),("B2",“B”),(“C1”,“C”),(“C2”,“C”),(“D1”,“D”),(“D2”,“D”),(“D”,"A"),("C","A"),("B","A")]foredgeinedges:G.add_edge(edge[0],edge[1])pagerank_list=nx.pagerank(G,alpha=1)print("pagerankvalueis:",pagerank_list)结果:整个数据集分为三个文件:Aliases.csv、Emails.csv和Persons.csv,其中Emails文件为Email内容,包括重要的发件人和收件人信息。Persons文件统计邮件中所有人的姓名和相应的ID。下面的代码直接取自数据实战。其实过程比较简单,但是这个思路比较重要。#-*-coding:utf-8-*-#使用PageRank挖掘希拉里邮件中的重要任务关系"./input/Emails.csv")#读取别名文件file=pd.read_csv("./input/Aliases.csv")aliases={}forindex,rowinfile.iterrows():aliases[row['Alias']]=row['PersonId']#读取名字文件file=pd.read_csv("./input/Persons.csv")persons={}forindex,rowinfile.iterrows():persons[row['Id']]=row['Name']#Convertforaliasesdefunify_name(name):#将名字统一为小写name=str(name).lower()#去掉,@name后面的内容=name.replace(",","").split("@")[0]#别名转换ifnameinaliases.keys():returnpersons[aliases[name]]returnname#绘制网络图defshow_graph(graph,layout='spring_layout'):#使用SpringLayout布局,类似于中心径向iflayout=='circular_layout':positions=nx.circular_layout(graph)else:positions=nx.spring_layout(graph)#设置网络图节点大小,大小pagerank值是有关系的,因为pagerank值很小,所以需要*20000nodesize=[x['pagerank']*20000forv,xingraph.nodes(data=True)]#设置边长in网络图edgesize=[np.sqrt(e[2]['weight'])foreingraph.edges(data=True)]#绘制节点nx.draw_networkx_nodes(graph,positions,node_size=nodesize,alpha=0.4)#绘制边nx.draw_networkx_edges(graph,positions,edge_size=edgesize,alpha=0.2)#绘制节点的标签nx.draw_networkx_labels(graph,positions,font_size=10)#输出希拉里邮件plt中的所有人物关系图.show()#发送邮件人名和收件人的名字是规范化的发送的电子邮件数量edges_weights_temp=defaultdict(list)forrowinzip(emails.MetadataFrom,emails.MetadataTo,emails.RawText):temp=(row[0],row[1])iftempnotinedges_weights_temp:edges_weights_temp[temp]=1else:edges_weights_temp[temp]=edges_weights_temp[temp]+1#转换格式(from,to),weight=>from,to,weightedges_weights=[(key[0],key[1],val)forkey,valinedges_weights_temp.items()]#创建有向图graph=nx.DiGraph()#设置有向图中的路径和权值(from,to,weight)graph.add_weighted_edges_from(edges_weights)#计算每个节点(person)的PR值,作为节点的pagerank属性pagerank=nx.pagerank(graph)#将pagerank值作为pagerank的属性节点nx.set_node_attributes(graph,name='pagerank',values=pagerank)#绘制网络图show_graph(graph)#简化完整图#设置PR值的阈值,过滤大于阈值的重要核心节点pagerank_threshold=0.005#复制一个计算好的网络图small_graph=graph.copy()#截掉pr值小于pagerank_threshold的节点forn,p_rankingraph.nodes(data=True):ifp_rank['pagerank']
