首页 > 编程问答 >有效地找到大图的近似最小生成树

有效地找到大图的近似最小生成树

时间:2024-07-29 09:49:48浏览次数:12  
标签:python algorithm scipy networkx minimum-spanning-tree

我有大量节点,大约 25000 个,每个节点都有 3D 位置。

我想生成一个稀疏连接的图,其边由节点之间的距离给出,以在 GNN 中使用。

查找算法最小生成树 (MST) 通常依赖于首先从完全连接的图开始,然后删除节点以找到 MST。对于大型图来说,这非常慢。

为了尝试加快速度,我尝试使用 scipy 的稀疏距离矩阵将初始连接的半径限制为最大最近邻距离,但这会导致某些图出现多个连接组件。|| |(此方法的较小图的示例不起作用:)

这是我尝试过的:

Example for a small graph

我不需要真正的最小生成树,只是为了使图与尽可能少的连接边缘以加速 GNN 性能。即使稀疏方法对于某些图来说也太慢了。

import numpy as np
from scipy.sparse.csgraph import minimum_spanning_tree
from scipy.spatial import KDTree
from scipy.spatial import distance_matrix

# Create a random set of 25000 node positions
positions = np.random.normal(loc=500000, scale=10000, size=(25000, 3))

# Method 1: Full MST Search (Too Slow)
dist_matrix = distance_matrix(positions, positions)
mst = minimum_spanning_tree(dist_matrix)


# Method 2: Start from sparse matrix (Results in multiple connected components)
kdtree = KDTree(positions)

# Find the maximum nearest neighbour distance for the graph
distances, _ = kdtree.query(positions, k=2)
max_neighbour_distance = np.max(distances[:, 1])
max_neighbour_distance = np.ceil(max_neighbour_distance) # Round up to avoid floating point errors in MST search


# Threshold the distance matrix by this distance
sparse_dist_matrix = kdtree.sparse_distance_matrix(kdtree, max_neighbour_distance, output_type="coo_matrix")

mst = minimum_spanning_tree(sparse_dist_matrix)

G = nx.from_scipy_sparse_array(mst)

我考虑了一种基于

https://www.cs.umd.edu/~mount/Papers/soda16-emst.pdf 的方法,但它看起来很难实现,即 scipy 没有四叉树。 将全距离矩阵转换为 networkx 图,然后使用他们的 Boruvka 算法的实现甚至更慢,它不适用于大型图。 向 max_neighbor_distance 添加一个乘数将有助于确保只有一个连接的组件,但也会增加处理时间,并且并不总是足够的。

Converting the fully distance matrix to a networkx graph then using their implementation of Boruvka's algorithm is even slower, it's not intended for large graphs. Adding a multiplier to max_neighbor_distance would help ensure there's only one connected component, but would also increase processing time and won't always be enough.


你遇到的问题很常见:你想要一个大型数据集的最小生成树的快速近似,以用于你的 GNN。虽然完整的 MST 计算成本高昂,但你是对的,仅基于最大近邻距离进行阈值化可能会导致不相交的组件。

让我们探讨一些可以帮助你实现速度和连通性的策略:

  1. 混合方法:K 近邻图 + MST

  2. 理念: 与其依赖单个阈值,不如构建一个保证连通性的初始图,然后对其进行修剪以获得稀疏性。

  3. 步骤:
    1. K 近邻图: 为你的数据集构建一个 K 近邻图。你可以使用 KDTree.query(k=K) 来有效地找到每个点的 K 个最近邻。选择一个小的 K 值(例如,3 到 5)以确保连通性,但不要太大以保持稀疏性。
    2. MST 计算: 在 K 近邻图上计算 MST。由于这个图已经比完全图稀疏得多,因此 MST 计算应该快得多。
  4. 优点: 保证连通性,并且比完全 MST 快。
  5. 缺点: MST 可能不是真正全局最优的,因为你从一个更密集的初始图开始。

  6. 增量边添加(类似于 Prim 算法)

  7. 理念: 以一个小的连通图开始,并迭代地添加连接现有图和剩余节点的最小成本边。

  8. 步骤:
    1. 初始化: 从一个包含单个节点的图开始。
    2. 迭代增长: 在连接现有图中的节点和图外的节点的边中找到成本最低的边。将这条边和相应的节点添加到图中。
    3. 终止: 重复步骤 2,直到所有节点都已连接。
  9. 优点: 逐渐构建 MST,避免了大型密集图。
  10. 缺点: 可能不如 K 近邻 + MST 方法快,具体取决于实现。

  11. 基于四叉树的近似(如果你需要非常大的规模)

  12. 理念: 虽然 scipy 没有直接的四叉树实现,但你可以使用其他库或探索近似方法。基于四叉树的分解可以帮助你递归地划分你的空间并找到连接不同区域的近似最小成本边。

  13. 库: 请查看 scikit-learn 中的 BallTree ,它可以很好地替代四叉树,并且在某些情况下性能甚至更好。
  14. 复杂性: 此方法的实现更加复杂,但对于非常大的数据集和需要严格控制近似误差的情况非常有用。

代码示例(K 近邻图 + MST):

import numpy as np
from scipy.sparse.csgraph import minimum_spanning_tree
from scipy.spatial import KDTree
import networkx as nx

# 创建一组随机的 25000 个节点位置
positions = np.random.normal(loc=500000, scale=10000, size=(25000, 3))

# 步骤 1:K 近邻图
k = 5  # 选择一个小 k 值
kdtree = KDTree(positions)
distances, indices = kdtree.query(positions, k=k + 1)  # 查询 k+1 个邻居,包括自身

# 从索引和距离创建稀疏矩阵
row_indices = np.repeat(np.arange(len(positions)), k)
col_indices = indices[:, 1:].flatten()  # 排除自身
data = distances[:, 1:].flatten()
sparse_dist_matrix = csr_matrix((data, (row_indices, col_indices)), shape=(len(positions), len(positions)))

# 步骤 2:MST 计算
mst = minimum_spanning_tree(sparse_dist_matrix)

# 创建 networkx 图以供使用
G = nx.from_scipy_sparse_array(mst)

提示:

  • 基准测试: 尝试不同的方法,并在你的特定数据集上对它们进行基准测试,以查看哪种方法提供最佳性能。
  • 参数调整: 诸如 K 值(对于 K 近邻)或四叉树分解中的误差容限等参数会影响结果的稀疏性和准确性。

请记住,找到完美的 MST 近似是一个权衡问题。目标是找到一种方法,在速度和保持图的连通性之间取得良好的平衡,以满足你的 GNN 应用程序的需求。

标签:python,algorithm,scipy,networkx,minimum-spanning-tree
From: 78805078

相关文章

  • Python反编译失败。 (不支持的操作码:JUMP_IF_NOT_EXC_MATCH)
    我尝试使用“pycdc.exe”反编译使用pycdc.exe失败。因为错误“不支持的操作码:JUMP_IF_NOT_EXC_MATCH”在此处输入图像描述使用pycdc.exe失败。因为错误“不支持的操作码:JUMP_IF_NOT_EXC_MATCH”你知道我为什么失败吗?(我试图编译的.pyc似乎是3.10版本)......
  • 计算机毕业设计项目推荐,基于Echarts的高校就业数据可视化管理系统 81461(开题答辩+程序
    摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对高校就业管理等问题,对高校就业管理进行研究分析,然后开发设计出高校就业数据可视化管理系统......
  • Python逆向总结(Python反编译)
    目录第一种:直接反编译型第二种:打包成exe的py文件第三种: 给pyc字节码(类汇编形式)第四种:加花的pyc内容参考第一种:直接反编译型除了直接获得题目内容的python文件外,出题人也可以稍微加工一点点,给出题目python文件所对应的pyc文件,即python的字节码。PYC文件的定义pyc......
  • 【Python学习手册(第四版)】学习笔记06-Python动态类型-赋值模型详解
    个人总结难免疏漏,请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。主要介绍Python的动态类型(也就是Python自动为跟踪对象的类型,不需要在脚本中编写声明语句),Python中变量和对象是如何通过引用关联,垃圾收集的概念,对象共享引用是如何影响多个变量......
  • Python学习手册(第四版)】学习笔记09.3-Python对象类型-分类、引用VS拷贝VS深拷贝、比较
    个人总结难免疏漏,请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。这部分稍杂,视需要选择目录读取。主要讲的是对之前的所有对象类型作复习,以通俗易懂、由浅入深的方式进行介绍,所有对象类型共有的特性(例如,共享引用),引用、拷贝、深拷贝,以及比较、......
  • 同时运行多个Python文件
    如何同时运行python的多个文件我有三个文件pop.pypop1.pypop2.py我想同时运行这个文件这些文件正在被一一运行python代码运行所有文件可以使用以下几种方法同时运行多个Python文件:1.使用多线程/多进程:多线程(threading):如果的Pytho......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-56- 多文件上传 - 下篇
    1.简介前边的两篇文章中,宏哥分别对input控件上传文件和非input控件上传文件进行了从理论到实践地讲解和介绍,但是后来又有人提出疑问,前边讲解和介绍的都是上传一个文件,如果上传多个文件,Playwright是如何实现的呢?宏哥看了一下官方的API也有上传多个文件的API,那么今天就来讲解和介绍......
  • 如何使用python模块捕获用户的文本输入
    我正在开发一个项目,它会检测到如果您按“(”,它会自动关闭它“[”和“{”的情况相同,但重点是它检测键盘按钮“{”或“[”不是字符,这意味着如果朋友有不同的方式输入“[”,它将无法工作,因为该程序用于检测“altgr+(”序列,这可能会影响不同语言的键盘因为您不想在按下......
  • 如何更新 numpy 2 的 python 模块?
    在带有pip的Linux上,新的numpy2似乎可以很好地与pandas配合使用:$python3-c'importnumpyasnp;print(np.__version__);importpandasaspd;print(pd.__version__)'2.0.12.2.2但是,在带有miniconda的Windows上,我得到$${localappdata}/miniconda3/en......
  • python BioChemist 数据集的数据字典/描述
    我正在使用生物化学家数据集。我在哪里可以找到包含每个变量描述的“数据字典”?这就是我正在查看的:importpandasaspdfrompydatasetimportdatadata('bioChemists')我已经用谷歌搜索并尝试寻找运算符,但没有运气!pydataset软件包不包含生物化学家数据集的描述......