PageRank算法

本文介绍了PageRank算法,它基于论文影响力因子思想,通过网页入链集合计算影响力。简化模型存在等级泄露和等级沉没问题,随机浏览模型引入阻尼因子解决。还介绍了networkx中实现PageRank的常用操作,如创建图、增删节点和边等,并给出用该算法挖掘希拉里邮件人物关系的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PageRank算法

PageRank算法基于论文影响力因子的思想提出:当一篇论文被引用的次数越多,证明这篇论文的影响力越大
PageRank 的简化模型:

在这里插入图片描述

一个网页的影响力 = 所有入链集合的页面的加权影响力之和,公式表示为:
PR(u)=∑v∈BuPR(v)L(v) P R(u)=\sum_{v \in B_{u}} \frac{P R(v)}{L(v)} PR(u)=vBuL(v)PR(v)
u 为待评估的页面,Bu为页面 u 的入链集合。针对入链集合中的任意页面 v,它能给 u带来的影响力是其自身的影响力 PR(v) 除以 v 页面的出链数量,统计所有能给 u 带来链接的页面 v,得到的总和就是网页 u
的影响力,即为 PR(u)。

对于上图中可以得到转移矩阵M:
M=[01/2101/3001/21/3001/21/31/200] M=\left[ \begin{array}{cccc}{0} & {1 / 2} & {1} & {0} \\ {1 / 3} & {0} & {0} & {1 / 2} \\ {1 / 3} & {0} & {0} & {1 / 2} \\ {1 / 3} & {1 / 2} & {0} & {0}\end{array}\right] M=01/31/31/31/2001/2100001/21/20
假设 A、B、C、D 四个页面的初始影响力都是相同的,则当进行第一次转移之后,各页面的影响力变为:
w1=Mw0=[01/2101/3001/21/3001/21/31/200][1/41/41/41/4]=[9/245/245/245/24] w_{1}=\mathrm{M} w_{0}=\left[ \begin{array}{cccc}{0} & {1 / 2} & {1} & {0} \\ {1 / 3} & {0} & {0} & {1 / 2} \\ {1 / 3} & {0} & {0} & {1 / 2} \\ {1 / 3} & {1 / 2} & {0} & {0}\end{array}\right] \left[ \begin{array}{c}{1 / 4} \\ {1 / 4} \\ {1 / 4} \\ {1 / 4}\end{array}\right]=\left[ \begin{array}{c}{9 / 24} \\ {5 / 24} \\ {5 / 24} \\ {5 / 24}\end{array}\right] w1=Mw0=01/31/31/31/2001/2100001/21/201/41/41/41/4=9/245/245/245/24
然后我们再用转移矩阵w1乘以w2得到结果,直到第 n 次迭代后影响力不再发生变化,可以收敛到 (0.3333,0.2222,0.2222,0.2222),也就是对应着 A、B、C、D 四个页面最终平衡状态下的影响力。

实际情况通常较为复杂,可能会面临两个问题:

  1. 等级泄露:如果一个网页没有出链,最终会导致其他网页的 PR 值为 0。
  2. 等级沉没::如果一个网页只有出链,没有入链,计算的过程迭代下来,会导致这个网页的 PR 值为 0。
PageRank随机浏览模型:为解决等级泄露和等级沉没的问题而提出。

定义了阻尼因子d,代表用户按照跳转链接上网的概率,通常可以取
一个固定值 0.85,而 1-d=0.15 则代表了用户不是通过跳转链接的方式来访问网页的。
PR(u)=1−dN+d∑v∈BuPR(v)L(v) P R(u)=\frac{1-d}{N}+d \sum_{v \in B_{u}} \frac{P R(v)}{L(v)} PR(u)=N1d+dvBuL(v)PR(v)
N 为网页总数,阻尼因子的加入一定程度上解决了等级泄露和等级沉没的问题。

networkx中实现PageRank方法的常用操作:
  1. 图的创建:

    图可以分为无向图和有向图

    无向图指的是不用节点之间的边的方向,使用 nx.Graph() 进行创建

    有向图指的是节点之间的边是有方向的,使用 nx.DiGraph() 来创建

  2. 节点增加、删除、查询

    G.add_node(‘A’) 添加一个节点

    G.add_nodes_from([‘B’,‘C’,‘D’,‘E’]) 添加节点集合

    G.remove_node(node) 删除一个指定的节点

    G.remove_nodes_from([‘B’,‘C’,‘D’,‘E’]) 删除集合中的节点

    G.nodes()得到图中所有节点

    G.number_of_nodes() 得到图中节点的个数

  3. 边的增加、删除、查询

    G.add_edge(“A”, “B”) 添加指定的“从 A 到B”的边

    add_edges_from 函数从边集合中添加

    add_weighted_edges_from 函数从带有权重的边的集合中添加,接收的是 1 个或多个三元组 [u,v,w] 作为参数,u、v、w 分别代表起点、终点和权重

    remove_edge 函数和 remove_edges_from 函数删除指定边和从边集合中删除

    edges() 函数访问图中所有的边

    number_of_edges() 函数得到图中边的个数

例使用PageRank挖掘希拉里邮件中人物关系:
import networkx as nx
import pandas as pd
import numpy as np
from collections import defaultdict
import matplotlib.pyplot as plt

#数据加载
emails = pd.read_csv('./Emails.csv')
#读取别名文件
file = pd.read_csv('./Aliases.csv')
aliases = {}
for index, row in file.iterrows():
    aliases[row['Alias']] = row['PersonId']
#读取人名文件
file = pd.read_csv('./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):
    #使用spring layout布局,中心放射状
    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()
#设置路径及权重
graph.add_weighted_edges_from(edges_weights)
#计算每个节点的PR值,并作为节点的PageRank属性
pagerank = nx.pagerank(graph)
#获取每个节点的PageRank数值
pagerank_list = {node:rank for node, rank in pagerank.items()}
#将pagerank数值作为节点的属性
nx.set_node_attributes(graph, name='pagerank', values=pagerank_list)
#画网络图
show_graph(graph)

#设置PR值的阈值,筛选大于阈值的重要核心节点
pagerank_threshold = 0.005
#复制一份计算好的网络图
small_graph = graph.copy()
#减掉PR值小于阈值的节点
for n, p_rank in graph.nodes(data=True):
    if p_rank['pagerank'] < pagerank_threshold:
        small_graph.remove_node(n)
        
#画网络图
show_graph(small_graph)

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sweeney Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值