当前位置: 首页 > news >正文

【GNN】第二章:图数据

【GNN】第二章:图数据

图数据和我们平时的看到的数据差别是很大的。先强调一下:图(graph)是图(graph),数据集(dataset)是数据集(dataset), 图是包含在数据集中的。一个数据集中可以只有一个图也可以有多个图。所以我们先讲图graph,然后再讲torch_geometric包中自带的数据集,最后讲如何将我们自己的数据转化为图数据。

一、图论的基本概念

该部分主要介绍图论的基本概念和基本的定义定理,也就是图数据的表示

1、图的定义1——图中的节点和边的表示
图(Graph)是一种表示对象之间关系的基本结构。具体的,我们用G=(V, E) 来表示图,其中V表示节点Nodes(也叫‘实体entities’) 的集合、E表示边Edges(也叫‘关系’relations) 的集合:

(1)节点和边本身是要embedding成一个特征向量的。这是自然喽,如果不是特征向量,神经网络怎么计算嘛。所以,一个图有三部分特征

一是,点特征。点是由特征向量来表示的。
二是,边特征。边也是用特征向量来表示的。比如如果要预测两个点之间的关系(朋友关系、亲人关系、同事关系)就是这两个点的边的特征。所以边也是一个向量。
三是,图特征。就是上图的U。图是一个全局的概念。图是由所有的点和所有的边组成的。所以比如所有的点的均值就可以表示图的特征。所有的边的特征的均值就也是图的特征。

(2)一般情况下,节点和边还要有自己的标签

节点和边的信息可以是类别型的(categorical),类别型数据的取值只能是哪一类别。一般称类别型的信息为标签(label)。
节点和边的信息可以是数值型的(numeric),数值型数据的取值范围为实数。一般称数值型的信息为属性(attribute)。

为什么要有标签?有标签就可以分类或回归了呀。所以,图神经网络是可以完成不同的任务
比如有的任务是求点的(比如对点进行分类、回归等任务),有的是求边的(比如对边进行分类、回归等任务),有的还是求全局的就是Graph级别的任务(比如设计分子结构等任务)。
为什么“一般情况下”有标签?意思就是可以只有部分标签,就是可以仅仅是一些重要的节点和重要的边才有标签,就是图神经网络可以进行半监督学习的,不是必须所有的节点和边都需要标签的。但是当然还是标签越多越好嘛。

但是无论数据多么随意,我们使用图神经网络的目的就是整合特征,或者说是重构特征。为什么要重构特征?因为每个点都不是孤立的,它都是和一些别的点有联系的,所以一个点的特征的变化是要受到和它有边相连的点的影响的。我们的图神经网络就是拟合(或者说‘捕获’)这种相互之间复杂的作用关系的。

2、图的定义2——图的拓扑结构:邻接矩阵(Adjacency Matrix)、邻接表(Adjacency List)
一个图数据,所有的节点特征、节点标签、边特征、边标签就可以表示一个图数据了嘛?显然是不够的!图的拓扑结构也是有决定作用的:

上面的两个图,它们同样都是有俩黄、俩蓝、俩绿,共6个节点,因此它们的节点信息相同;假如边只表示一种关系,那么它们的边信息也相同。但这两个图显然是不一样的图,因为它们的拓扑结构不一样!所以图的拓扑结构同样也包含了这个图的重要信息,这些拓扑信息后面还要辅助深度学习网络计算节点表征的,就是上面提到的是要辅助“重构特征”的。所以我们还得把图的拓扑结构也用数字表示出来。

如何表示一个图的拓扑结构呢?通常有两种方案:邻接矩阵邻接表
邻接矩阵是反映哪两个节点之间有边的矩阵,也是告诉神经网络节点之间的关系的矩阵。邻接矩阵是一个NxN矩阵的形式。
但是有时,当节点非常多的时候,邻接矩阵就会太大,所以有时我们用邻接表来表示一个图的拓扑结构。邻接表是以 (source, target)对儿 的形式存储的,是一种顺序分配和链式分配相结合的存储结构。

(1)所以:NxN邻接矩阵是一个0101的稀疏矩阵;也是一个对称矩阵。
(source,target)对儿的邻接表一个n行2列的矩阵,其中[v1,v2]表示节点v1和节点v2之间是有边的,[v1,v3]表示节点v1和节点v3之间是有边的,其他行同理。
邻接矩阵(邻接表)作为图数据的重要信息,是要作为输入一并传入GNN模型的,GNN在计算节点和边的特征时,邻接矩阵(邻接表)是要参与计算的,具体怎么参与计算,后面讲网络架构原理时会详细展开讲。

(2)上图是一个无向图(Undirected Graph),就是节点v1到节点v2的边存在,就意味着从节点v2到v1的边也是存在的。所以无向图的邻接矩阵是对称的,有向图(Directed Graph)的邻接矩阵是不对称的

(3)上图还是一个无权图,就是各条边的权重被认为是等价的,即认为各条边的权重都是1。所以如果是一个有权图,那它对应的邻接矩阵Aij=wij,就是从节点vi到vj的边的权重,若边不存在时,边的权重为0。

3、图的属性1——节点的度(Degree)
节点的度就是指一个节点有多少条边和它连接。但是在有权有向图中,边就不仅有方向还有权重,所以一个节点的(Degree)就被细分为这个节点的出度(out degree)和入度(in degree)。
显然,出度(dout(vi))就是从节点vi出发的边的权重之和入度(din(vi))就是所有连向节点vi的边的权重之和

无向图是有向图的特殊情况,所以无向图的节点的出度和入度相等。
无权图又是有权图的特殊情况,无权图的权重为1,所以无权图的节点vi的出度=从vi出发的边的数量,节点vi的入度=所有连向vi的边的数量。

下面是计算一个图的节点的度矩阵(Degree Matrix):

度矩阵也非常非常重要,以后我们讲网络数据传播时,度矩阵也是要和邻接矩阵一样,二者一起要参与节点表征的计算的。

4、图的属性2——邻接节点(neighbors)
与节点vi直接相连的节点,就是节点vi的邻接节点。比如上图的节点A的邻接节点就是E,而节点E的邻接节点是ABCD四个节点。
vi节点k跳远的邻接节点(neighbors with k-hop),指的是到节点vi走k步的节点(一个节点的2跳远的邻接节点包含了自身)。

5、图的属性3——行走(walk)、路径(path)、最短路径(shortest path)

6、图的属性4——子图(subgraph)、连通分量(connected component)、连通图(connected graph)、直径(diameter)

7、图的属性5——拉普拉斯矩阵 (Laplacian Matrix)

说明:上面图论的相关概念仅仅是非常非常少的一部分,也是最常用的一些概念。如果你想知道的更多,可以参考: https://cse.msu.edu/~mayao4/dlg_book/chapters/chapter2.pdf

二、图分析工具:NetworkX

一般我们拿到数据后,都想先可视化一下,直观的了解一下数据,所以这里我先讲一个图论领域常用的工具networkx。

NetworkX是一个图论和网络分析Python软件包,可以提供丰富的图数据结构和算法,创建、操作和分析各种类型的图。这个工具直接pip install networkx就安装好了。

NetworkX可以创建各种类型的图对象,比如无向图、有向图、有权图等;
NetworkX可以设置节点和边的属性、获取图的邻接矩阵、度、平均度、度分布、度矩阵等;
NetworkX可以进行图分析,因为它内置了很多图论算法,比如图的遍历、最短路径、社区发现、中心性等;
NetworkX可以绘制图对象,支持图数据的可视化,经常用于绘制网络结构。

1、举几个使用例子




上面只是入门一下这个工具包,其实这个工具包是非常强大的,经常用于复杂网络拓扑结构统计指标计算、典型复杂网络建模(随机图、小世界、无标度等)以及复杂网络可视化的方法等,值得花时间熟悉一下。

2、举一个交通网络优化的小案例:提升城市交通效率的路径优化
假设我们有一个城市的交通网络,由多个路口(节点)和道路(边)组成。我们的目标是从城市的某个起点(比如A点)到达某个终点(比如B点),我们希望:
一是,找到最短路径:从A到B的最短路径。
二是,找到最大流路径:在交通高峰期间,如何最大化从A到B的车辆通过量。
三是,避免拥堵:找到一条尽量避开拥堵区域的路径。

import networkx as nx
# 创建一个有向图来表示交通网络
G = nx.DiGraph()  

# 添加节点(路口)
nodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
G.add_nodes_from(nodes)

# 添加带权重的边(道路)及其通行能力
edges = [('A', 'B', {'weight': 2, 'capacity': 100}),  #就是给边设置属性,一个属性是weight,一个属性是capacity
         ('A', 'C', {'weight': 5, 'capacity': 50}),   #weight你可以理解为大家走这条路的“平均用时”
         ('B', 'C', {'weight': 2, 'capacity': 100}),  #capacity你可以理解为这条路的“最大通行量”
         ('B', 'D', {'weight': 4, 'capacity': 70}),
         ('C', 'E', {'weight': 1, 'capacity': 120}),
         ('D', 'F', {'weight': 3, 'capacity': 80}),
         ('E', 'F', {'weight': 1, 'capacity': 150}),
         ('F', 'G', {'weight': 2, 'capacity': 90}),
         ('E', 'H', {'weight': 3, 'capacity': 60}),
         ('H', 'G', {'weight': 2, 'capacity': 70}),]
G.add_edges_from(edges)

# 可视化交通网络
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']    #这行代码是用来让图上显示汉字的
plt.figure(figsize=(10, 6))   #搞一个画布
pos=nx.spring_layout(G)   #这种模式是随机的,所以别让它运行两次!
nx.draw(G, with_labels=True, node_size=1500, font_size=20, font_weight='bold', pos=pos)
nx.draw_networkx_edge_labels(G, pos=pos, font_size=15,
                             edge_labels={(i,j): f"w:{k['weight']},  c:{k['capacity']}" for i,j,k in G.edges(data=True)})  #这个参数只接收字典的形式
                            
G.edges(data=True)
plt.title("城市交通网络图")  #弄一个标题
plt.show()

#1、基于权重,也就是基于时间,找到从A到G的最短路径  
shortest_path = nx.shortest_path(G, source='A', target='G', weight='weight')
shortest_path_length = nx.shortest_path_length(G, source='A', target='G', weight='weight')  #这是最短路径用时
shortest_path, shortest_path_length

#2、找到最大流量路径
max_flow_value, max_flow_dict = nx.maximum_flow(G, 'A', 'G',capacity='capacity')
max_flow_value, max_flow_dict

#3、避免拥堵的路径(通过增加某些边的权重来模拟拥堵路径)
# 我们假设边 ('B', 'C') 和 ('E', 'F') 在高峰期很拥堵,因此增加它们的权重
G['B']['C']['weight'] += 10
G['E']['F']['weight'] += 10
# 重新计算最短路径
congestion_avoidance_path = nx.shortest_path(G, source='A', target='G', weight='weight')
congestion_avoidance_path_length = nx.shortest_path_length(G, source='A', target='G', weight='weight')
congestion_avoidance_path, congestion_avoidance_path_length

待续。。。。。

相关文章:

  • 【电路笔记 TMS320C6***DSP】外部存储器接口 A EMIFA向FPGA(作为异步存储器)写入数据的示例
  • Python学习(十四)pandas库入门手册
  • 自学Java-JavaSE基础加强(File、IO流)
  • 市场趋势解析与交易策略优化
  • C# Unity 面向对象补全计划 之 [反射]自动处理带有自定义[特性]的类
  • 对celery的,路径,任务路径问题。
  • QDBus:Qt对DBus的封装支持
  • Springboot集成dubbo完整过程(三)
  • gitbash忽略未追踪文件的解决方式
  • 四阶龙格-库塔(Runge-Kutta)算法详解
  • STM32Cubemx配置E22-xxxT22D lora模块实现定点传输
  • 数据库事务的 ACID,通过MVCC能做什么
  • qt将文件压缩成zip包
  • 【软件系统架构】系列三:数据库系统之三
  • Qt:day4
  • DeepSeek本机部署(基于Ollama和Docker管理)
  • 第六十:跨组件通信-依赖注入(父传递给其他组件)
  • C# | 委托 | 事件 | 异步
  • Varjo XR-4 混合现实驾驶仿真解决方案
  • 迷你世界脚本UI五子棋小游戏
  • 民房做酒店出租网站app/搜索关键词排名优化服务
  • seo提高网站排名/贵州百度seo整站优化
  • 开发网站公司名称/网络营销在哪里学比较靠谱
  • 公司网站建设ppt/免费做网站网站的软件
  • 网站如何换服务器/中国seo关键词优化工具
  • 想开一家网店/品牌推广百度seo