一篇学会 PageRank 算法与实践
如果让我们自己去做搜索的篇学话,我们能够想到的法实是文章和搜索词的相关性,以此来判断这个文章是篇学否是我们想要的,最开始的法实搜索有的是这样做的,还有的篇学是按照网站的种类做个大的索引表,但是法实可以索引的关键字有限。
互联网上的篇学网页估计有千百亿规模了(猜测),那么显然不是法实所有包含搜索关键字的网页都同等重要。有的篇学在标题中包含关键字,有的法实在文档中包含关键字;有的是权威机构网站,源码库有的篇学是个人博客,显然在给用户返回网页的法实时候,比较重要的篇学网页的应该排在前面,不重要的法实网页信息排在后面。那又来一个问题,篇学如何确定一个网页的重要性那。
网页是通过链接来组织的,那么我们可以把整个互联网看成一张大的图,每个节点为一个个网页,网页之间的链接看成边。网页是否重要,要看是否有多个网页链接到它。被越多网页链接的网页越重要,当然链接这个网页的多个链接的重要性又是不相同的。
假设我们搜索得到很多网页,b2b信息网其中一个网页Y的排名应该来自所有指向这个网页X1,X2,X3的权重之和:
Y网页的权重 = X1+X2+X3...+Xn
而X1,X2,...Xn的权重分别是多少,如何度量,这又需要通过链接到它的网页的权重来计算,这样循环往复,就无解了。据说是Google的布林破解了这个怪圈,就是开始的时候给每个网页设置相同的初始值,那么经过多轮计算后,这个算法可以保证网页排名多次之后回收敛到排名的真实值。
我理解下,大概是这样子的:

第一轮的时候,我们假设所有网页的权重都是云服务器1,那么A这个网页的权重为1+1+1为3, 第二轮计算的时候,与A相连的网页权重变成了2,那么最终A这个网页的权重就变成了2+2+2=6,这样多次计算后,被更多权重高的网页链接的网页,排名靠前,其他的靠后。
这整个过程有点类似于民主选举,选举过程中每个人的票的权重又是不一样的,这和现实也很类似。 那么PageRank算法除了计算网页排名还有什么用那,数据实战45讲里面,有个例子比较有意思,计算泄露出来希拉里邮件列表中的人物影响力的情况,通过python的networkx库可以方便地计算PageRank的值。
下面的网络图的:

简单的计算PageRank的代码:
import networkx as nx
# 创建有向图
G = nx.DiGraph()
# 有向图之间边的关系
edges = [("B1", "B"), ("B2", "B"), ("C1", "C"), ("C2", "C"), ("D1", "D"), ("D2", "D"), ("D", "A"), ("C", "A"), ("B", "A")]
for edge in edges:
G.add_edge(edge[0], edge[1])
pagerank_list = nx.pagerank(G, alpha=1)
print("pagerank值是:", pagerank_list)结果:

整个数据集合分为三个文件:Aliases.csv,Emails.csv和Persons.csv,其中Emails文件为邮件内容,包括重要的发送者和接收者信息。 Persons文件统计邮件中所有人的姓名和对应ID。 下面代码是数据实战中的代码直接拿过来了,其实过程也是比较简单,只是这个思路比较重要。
# -*- coding: utf-8 -*-
# 用 PageRank 挖掘希拉里邮件中的重要任务关系
import pandas as pd
import networkx as nx
import numpy as np
from collections import defaultdict
import matplotlib.pyplot as plt
# 数据加载
emails = pd.read_csv("./input/Emails.csv")
# 读取别名文件
file = pd.read_csv("./input/Aliases.csv")
aliases = {}
for index, row in file.iterrows():
aliases[row[Alias]] = row[PersonId]
# 读取人名文件
file = pd.read_csv("./input/Persons.csv")
persons = {}
for index, row in file.iterrows():
persons[row[Id]] = row[Name]
# 针对别名进行转换
def unify_name(name):
# 姓名统一小写
name = str(name).lower()
# 去掉, 和 @后面的内容
name = name.replace(",","").split("@")[0]
# 别名转换
if name in aliases.keys():
return persons[aliases[name]]
return name
# 画网络图
def show_graph(graph, layout=spring_layout):
# 使用 Spring Layout 布局,类似中心放射状
if layout == circular_layout:
positions=nx.circular_layout(graph)
else:
positions=nx.spring_layout(graph)
# 设置网络图中的节点大小,大小与 pagerank 值相关,因为 pagerank 值很小所以需要 *20000
nodesize = [x[pagerank]*20000 for v,x in graph.nodes(data=True)]
# 设置网络图中的边长度
edgesize = [np.sqrt(e[2][weight]) for e in graph.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)
# 绘制节点的 label
nx.draw_networkx_labels(graph, positions, font_size=10)
# 输出希拉里邮件中的所有人物关系图
plt.show()
# 将寄件人和收件人的姓名进行规范化
emails.MetadataFrom = emails.MetadataFrom.apply(unify_name)
emails.MetadataTo = emails.MetadataTo.apply(unify_name)
# 设置遍的权重等于发邮件的次数
edges_weights_temp = defaultdict(list)
for row in zip(emails.MetadataFrom, emails.MetadataTo, emails.RawText):
temp = (row[0], row[1])
if temp not in edges_weights_temp:
edges_weights_temp[temp] = 1
else:
edges_weights_temp[temp] = edges_weights_temp[temp] + 1
# 转化格式 (from, to), weight => from, to, weight
edges_weights = [(key[0], key[1], val) for key, val in edges_weights_temp.items()]
# 创建一个有向图
graph = nx.DiGraph()
# 设置有向图中的路径及权重 (from, to, weight)
graph.add_weighted_edges_from(edges_weights)
# 计算每个节点(人)的 PR 值,并作为节点的 pagerank 属性
pagerank = nx.pagerank(graph)
# 将 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 的节点
for n, p_rank in graph.nodes(data=True):
if p_rank[pagerank] < pagerank_threshold:
small_graph.remove_node(n)
# 画网络图,采用circular_layout布局让筛选出来的点组成一个圆
show_graph(small_graph, circular_layout)相关文章
电脑开机不出密码错误的原因与解决方法(探究密码错误问题及有效解决方案)
摘要:在日常使用电脑的过程中,我们经常会遇到电脑开机后输入密码却提示密码错误的问题。这不仅给我们的使用带来困扰,也可能导致无法正常登录系统。本文将针对这一问题展开讨论,分析可能的原因,并...2025-11-04
域名停用还能恢复吗?域名怎么设置停用?域名停用,如果在有效期内,则可以暂停所有解析记录,或者直接删除,从而达到停用的效果。当然,您也可以等待域名过期,一旦过期,域名将被禁用。下面聚名网小编就带大家看看2025-11-04
Lock基本使用Lock它是java.util.concurrent.locks下的一个接口,它也是用来处理线程同步问题的。public interface Lock {void lock();voi2025-11-04
SpringBoot如何保证接口的幂等性?六种方案一次讲清楚~
来源:JAVA日知录1. 幂等概述1.1 深入理解幂等性在计算机领域中,幂等Idempotence)是指任意一个操作的多次执行总是能获得相同的结果,不会对系统状态产生额外影响。在Java后端开发中,幂2025-11-04电脑自动安装系统完整教程(轻松实现系统自动化安装,提高效率)
摘要:随着科技的进步,电脑系统的安装变得越来越简单快捷。本文将为大家介绍一种自动安装系统的方法,帮助大家节省时间和精力,提高效率。了解电脑自动安装系统的意义... 随着科2025-11-04
二手域名怎么样购买?二手域名如何进行交易?二手域名交易流程是怎样的?下面小聚就给大家详解下有关二手域名购买和交易流程的事项。1. 二手域名交易,简单来说就是域名持有人售出域名,投资人、机构或终端买入域2025-11-04

最新评论