经典机器学习算法——Pagerank算法(二)

简介: PageRank 算法由 Google 创始人 Larry Page 在斯坦福读大学时提出,又称 PR——佩奇排名。主要针对网页进行排名,计算网站的重要性,优化搜索引擎的搜索结果。PR 值是表示其重要性的因子

二、Spider Traps问题

问题描述

Spider traps问题是PageRank算法中的一种现象,它指的是某些网页故意设计只有入链以及指向自己的出链,即自环,以此来提升网页的重要性

出现原因及解释

原因:网页只有入链以及指向自己的出链

解释:

  1、利用佩奇算法确定网站的重要性可以理解为:让一个小虫子在网站间不停且随机地爬,它爬到哪个网站的次数最多,则这个网站的重要性就越高


   2、当出现这种问题,小虫子走到Traps节点时,由于该节点没有出链只有自环。所有小虫子会在这个节点不停的循环走,这就会导致该节点的重要性不停提高直到1,而其他节点的重要性降低到0

图解示例

按照这个规律,我们在多次循环之后,会发现这个模型中 A 的 PR 值都会归于 1,其他归为 0

解决方法

image.png

1、选择概率 为跟随出链,正确打开网页的概率。1- 为随机打开网页的概率

2、按照概率 加权分配这个概率矩阵

PageRank算法问题解决总结

1、两个问题的解决都利用:修正M矩阵

2、前者直接加上修正矩阵,使得不存在全为0的列即可

3、后者需要对M矩阵进行等比例缩小,再加上加权处理后的修正矩阵。如此,才能让矩阵中不再存在为1的值

4、Spider Traps的解决方法不可以用于Dead ends。原因如下:

image.png

5、 Dead ends的解决方法不能用于Spider Traps,原因是直接加上一个矩阵,Spider Traps为1的值仍然无法解决

6、两个方法的限制点:a. 列之和为1;b. 不能存在为1的值

7、 值越大表明按照链接正常跳转的概率越大,这也意味这爬虫的移动会在相邻节点间进行,模型收敛速度变慢;反之值越少,随机链接访问的概率越大,这样意味着模型各网站的重要性相差越近,模型收敛速度越快

PageRank代码实现

导包解决法

import matplotlib.pyplot as plt
import networkx as netx  # 网络图库:生成构造网络图,并对网络图进行各类分析
import random
 
random.seed(42)  # 设置随机数种子,让结果可以复现
diGraph = netx.DiGraph()  # 生成有向图
diGraph.add_nodes_from(range(0, 100))  # range生成一个可迭代对象(迭代器:1、访问工具,本身不是具体的数据类型,可以对各种数据类型进行迭代;2、动态生成值,在每一次运行时动态加载到内存)
for i in range(100):
    j = random.randint(0, 100)
    k = random.randint(0, 100)
    diGraph.add_edge(k, j)
 
# 绘图
netx.draw(diGraph, with_labels=True)
plt.show()
 
# 计算并生成PR值
prValue = netx.pagerank(diGraph, max_iter=500, alpha=0.85)  # 生成的对象是一个字典类型
 
# 对PR值进行排序
prValue_list = list(prValue.items())  # 利用items(视图元组,不是实际元组)将字典转为元组,再用list将元组转为列表(可迭代访问对象)
 
# 使用 sorted() 函数对 prValue_list 进行排序,按照值(即 PageRank 值)从大到小排序
sorted_prValue = sorted(prValue_list, key=lambda x: x[1], reverse=True)
 
print(sorted_prValue)
 

手搓代码版

代码可以分为三个部分:

1、随机有向图的生成;2、根据有向图生成马尔科夫矩阵;3、利用马尔科夫矩阵计算PR值

这里我创建一个Python项目——PageRank

项目下有四个子项目:graph_generate.py、matrix_generate.py、pagerank.py、main.py

一、随机有向图的生成

graph_generate.py子项目

import networkx as nx
import matplotlib.pyplot as plt
 
def get_init_pr(dg):
    """
    获得每个节点的初始PR值
    :param dg: 有向图
    """
    nodes_num = dg.number_of_nodes()
    for node in dg.nodes:
        pr = 1 / nodes_num
        dg.add_nodes_from([node], pr=pr)
 
 
def create_network():
    """
    创建有向图
    :return dg: 有向图
    """
    dg = nx.DiGraph()  # 创建有向图
    dg.add_nodes_from(['0', '1', '2', '3', '4'])  # 添加节点
    dg.add_edges_from([('1', '0'), ('2', '1'), ('3', '4'), ('4', '1'), ('3', '1')])  # 添加边
 
    get_init_pr(dg)
 
    return dg
 
 
def draw_network(dg):
    """
    可视化有向图
    :param dg: 有向图
    """
    fig, ax = plt.subplots()
    nx.draw(dg, ax=ax, with_labels=True)
    plt.show()
 

二、根据有向图生成马尔科夫矩阵

matrix_generate.py子项目

import numpy as np
 
def solve_ranking_leaked(adj_matrix):
    """
    解决Dead Ends问题(也称为排名泄露问题)
    :param adj_matrix: 邻接矩阵
    """
    col_num = np.size(adj_matrix, 1)  # 获得邻接矩阵列数
 
    row_num = 0  # 用来统计矩阵的行数(只有通过出度的问题检查才算)
    for row in adj_matrix:
        # 如果排名泄露,那么修改这个节点对每个节点都有出链
        if sum(row) == 0:  # 这个节点出度为0,表明它存在排名泄露问题
            for col in range(col_num):
                adj_matrix[row_num][col] = 1
        row_num += 1
 
 
def calc_out_degree_ratio(adj_matrix):
    """
    计算每个节点影响力传播的比率,即该节点有多大的概率把影响力传递给下一个节点
    公式:
        out_edge / n
        out_edge: 出边,即这个节点可以把影响力传递给下一个节点
        n: 这个节点共有多少个出度
    :param adj_matrix: 邻接矩阵
    """
    row_num = 0
    for row in adj_matrix:  # 每次都拿出一个行列表
        n = sum(row)  # 求该节点的所有出度
        col_num = 0
        for col in row:
            adj_matrix[row_num][col_num] = col / n  # out_edge / n
            col_num += 1
 
        row_num += 1
 
 
def create_matrix(dg):
    """
    通过有向图生成邻接矩阵
    :param dg: 有向图
    :return adj_matrix: 邻接矩阵
    """
    node_num = dg.number_of_nodes()
 
    adj_matrix = np.zeros((node_num, node_num))
 
    for edge in dg.edges:
        adj_matrix[int(edge[0])][int(edge[1])] = 1
 
    solve_ranking_leaked(adj_matrix)
    calc_out_degree_ratio(adj_matrix)
    # print(adj_matrix)
    return adj_matrix
 
 
def create_pr_vector(dg):
    """
    创建初始PR值的向量
    :param dg: 有向图
    :return pr_vec: 初始PR值向量
    """
    pr_list = []
    nodes = dg.nodes
 
    # 将初始PR值存入列表
    for node in nodes:
        pr_list.append(nodes[node]['pr'])
 
    pr_vec = np.array(pr_list)  # 将列表转换为ndarray对象
 
    return pr_vec

三、 利用马尔科夫矩阵计算PR值

pagerank.py子项目

import numpy as np
import matplotlib.pyplot as plt
 
# 设置阻尼因子(跳转因子)防止Spider traps问题
alpha = 0.85  # 跳转因子
 
 
def draw(iter_list, pr_list):
    """
    绘制收敛图
    :param iter_list: 迭代次数列表
    :param pr_list: 每一个向量的值
    :return:
    """
    plt.plot(iter_list, pr_list)
    plt.show()
 
 
def pagerank(adj_matrix, pr_vec):
    """
    pagerank算法:
        V_{i+1} = alpha * V_i * adj + (1 - alpha) * E/ N
        (这个公式和上文介绍的略有不同,但是这两个是等价的)
         按照上文解决Spider Traps的方法,公式应该为:
                V_{i+1} = (alpha  * adj + ((1 - alpha) / N) * E)* V_i
    收敛条件:
        1. V_{i+1} == V_i
        2. 迭代次数200次
    就是说如果PR向量并没有发生改变,那么收敛结束,得到的PR值就是最终的PR值
    但是假设迭代次数过高后且未发生收敛,那么就会陷入死循环等,根据前人总结的经验,设置为迭代20次
    :param adj_matrix: 邻接矩阵
    :param pr_vec: 每个节点PR值的初始向量
    :return:
    """
    num_nodes = np.size(adj_matrix, 1)  # 获得矩阵列数(ie. 节点数)
    jump_value = (1 - alpha) / num_nodes  # 从其他页面跳转入所在页面的概率(标量)
    jump_vec = jump_value * np.ones(num_nodes)  # 向量化
 
    # iter_list = []
    # pr_list = []
 
    for n_iter in range(1, 201):
        pr_new = alpha * np.dot(pr_vec, adj_matrix) + jump_vec
 
        print("第{0}次迭代的PR值:{1}".format(n_iter, pr_new))
 
        # iter_list.append(n_iter)
        # pr_list.append(tuple(pr_new))
 
        if (pr_new == pr_vec).all():
            break
        # else:
        #     # 调试用
        #     test = pr_new - pr_vec
 
        pr_vec = pr_new
 
    # draw(iter_list, pr_list)
 
    print("迭代完成!")
    print("收敛值为:", pr_vec)

总结

       PageRank 算法是现代数据科学中用于图链接分析的经典方法,最初由LarryPage 和Sergey Brin 在1996年提出。两位斯坦福大学研究生认为互联网上的链接结构能够反映页面的重要性,与当时基于关键词的搜索方法形成对比。这一独特观点不仅赢得了学术界的认可,也为后来创建的Google搜索引擎奠定了基础。

       PageRank的核心思想基于有向图上的随机游走模型,即一阶马尔可夫链。描述了随机游走者如何沿着图的边随机移动,最终收敛到一个平稳分布。在这分布中,每个节点被访问的概率即为其PageRank值,代表节点的重要性。 PageRank是递归定义的,计算需要迭代方法,因为一个页面的值部分取决于链接到它的其他页面的值。尽管最初设计用于互联网页面,但PageRank已广泛应用于社会影响力、文本摘要等多个领域,展示了其在图数据上的强大实用性

撰写文章不易,如果文章能帮助到大家,大家可以点点赞、收收藏呀~

03fa97f2d76e0c5562b39c6c5c8f8bb0_a951ae90b4df4f908b7eeaf02af68b82.gif

相关文章
|
5天前
|
机器学习/深度学习 数据采集 自然语言处理
理解并应用机器学习算法:神经网络深度解析
【5月更文挑战第15天】本文深入解析了神经网络的基本原理和关键组成,包括神经元、层、权重、偏置及损失函数。介绍了神经网络在图像识别、NLP等领域的应用,并涵盖了从数据预处理、选择网络结构到训练与评估的实践流程。理解并掌握这些知识,有助于更好地运用神经网络解决实际问题。随着技术发展,神经网络未来潜力无限。
|
2天前
|
机器学习/深度学习 算法 数据处理
探索机器学习中的决策树算法
【5月更文挑战第18天】探索机器学习中的决策树算法,一种基于树形结构的监督学习,常用于分类和回归。算法通过递归划分数据,选择最优特征以提高子集纯净度。优点包括直观、高效、健壮和可解释,但易过拟合、对连续数据处理不佳且不稳定。广泛应用于信贷风险评估、医疗诊断和商品推荐等领域。优化方法包括集成学习、特征工程、剪枝策略和参数调优。
|
4天前
|
机器学习/深度学习 算法 数据挖掘
【机器学习】K-means算法与PCA算法之间有什么联系?
【5月更文挑战第15天】【机器学习】K-means算法与PCA算法之间有什么联系?
|
4天前
|
机器学习/深度学习 算法 数据挖掘
【机器学习】维度灾难问题会如何影响K-means算法?
【5月更文挑战第15天】【机器学习】维度灾难问题会如何影响K-means算法?
|
5天前
|
机器学习/深度学习 算法 数据挖掘
【机器学习】聚类算法中,如何判断数据是否被“充分”地聚类,以便算法产生有意义的结果?
【5月更文挑战第14天】【机器学习】聚类算法中,如何判断数据是否被“充分”地聚类,以便算法产生有意义的结果?
|
5天前
|
机器学习/深度学习 运维 算法
【机器学习】可以利用K-means算法找到数据中的离群值吗?
【5月更文挑战第14天】【机器学习】可以利用K-means算法找到数据中的离群值吗?
|
5天前
|
机器学习/深度学习 分布式计算 并行计算
【机器学习】怎样在非常大的数据集上执行K-means算法?
【5月更文挑战第13天】【机器学习】怎样在非常大的数据集上执行K-means算法?
|
5天前
|
算法 数据安全/隐私保护 计算机视觉
基于二维CS-SCHT变换和LABS方法的水印嵌入和提取算法matlab仿真
该内容包括一个算法的运行展示和详细步骤,使用了MATLAB2022a。算法涉及水印嵌入和提取,利用LAB色彩空间可能用于隐藏水印。水印通过二维CS-SCHT变换、低频系数处理和特定解码策略来提取。代码段展示了水印置乱、图像处理(如噪声、旋转、剪切等攻击)以及水印的逆置乱和提取过程。最后,计算并保存了比特率,用于评估水印的稳健性。
|
2天前
|
算法
m基于BP译码算法的LDPC编译码matlab误码率仿真,对比不同的码长
MATLAB 2022a仿真实现了LDPC码的性能分析,展示了不同码长对纠错能力的影响。短码长LDPC码收敛快但纠错能力有限,长码长则提供更强纠错能力但易陷入局部最优。核心代码通过循环进行误码率仿真,根据EsN0计算误比特率,并保存不同码长(12-768)的结果数据。
20 9
m基于BP译码算法的LDPC编译码matlab误码率仿真,对比不同的码长
|
3天前
|
算法
MATLAB|【免费】融合正余弦和柯西变异的麻雀优化算法SCSSA-CNN-BiLSTM双向长短期记忆网络预测模型
这段内容介绍了一个使用改进的麻雀搜索算法优化CNN-BiLSTM模型进行多输入单输出预测的程序。程序通过融合正余弦和柯西变异提升算法性能,主要优化学习率、正则化参数及BiLSTM的隐层神经元数量。它利用一段简单的风速数据进行演示,对比了改进算法与粒子群、灰狼算法的优化效果。代码包括数据导入、预处理和模型构建部分,并展示了优化前后的效果。建议使用高版本MATLAB运行。

热门文章

最新文章