图的基本概念:节点、边、度、邻接矩阵、图的连通性

各位好,今天我们来聊聊图——不是那种柱状折线图,而是由节点和边构成的数学结构。说实话,我在做药物分子性质预测时天天跟图打交道。分子里的原子就是节点,化学键就是边。不理解这些基础,后面的GNN模型根本没法上手。

节点与边:图的基石

图由两部分组成:节点(也叫顶点)和边(连接节点的关系)。

  • 节点:代表实体,比如药物分子中的原子、社交网络里的人。
  • 边:代表实体之间的关系,比如化学键、朋友关系。
我个人习惯用 V 表示节点集合,E 表示边集合。图记作 G = (V, E)。写代码时我会把节点ID从0开始编,这样跟数组下标对齐,不容易出错。

边可以是有方向的(有向图),也可以是无方向的(无向图)。比如蛋白质相互作用网络通常是无向图,而化学反应路径往往是有向图。我曾经在项目中把无向图当成有向图处理,结果特征矩阵少了一半对称项,模型训练半天不收敛……嗯,这个坑你们别踩。

度:节点的重要性指标

节点的度就是它连接的边数。在无向图中,度就是邻居数量。有向图里分入度和出度。

图类型度的定义例子
无向图邻居个数一个原子连接3个其他原子,度=3
有向图入度/出度一个靶点被多个药物靶向,入度较高

为什么度很重要?在药物节点分类中,度高的节点往往扮演枢纽角色,比如与很多蛋白相互作用的代谢物。我做分子图分类时,会把度作为节点特征直接丢进模型,效果比纯One-hot好一倍。

邻接矩阵:图的数字骨架

邻接矩阵是表示图的标准数据结构。对于一个有 n 个节点的图,矩阵是 n × n 的方阵。如果节点 i 和 j 之间有边,那么 A[i][j] = 1(加权图可以是非1权重),否则为0。

邻接矩阵的优点:矩阵运算可以直接套用线性代数工具。缺点是稠密图还好,稀疏图(大部分药物分子图)存起来像张渔网——浪费空间。

我习惯用稀疏矩阵(比如scipy的CSR格式)来存大分子图。曾经有个同事直接用浮点表示存储,一个1000个原子的分子图就爆内存了。你想想看,光0就占了99%的格子。

下面这张SVG图展示了5个节点的无向图,每个节点标注了度,右侧是它的邻接矩阵。

无向图及其邻接矩阵示例 0 1 2 3 4 度=2 度=2 度=2 度=2 度=1 邻接矩阵 A 0 1 1 0 0 1 0 1 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 1 0

图的连通性:整体与子结构

连通性描述图是否“抱成一团”。无向图中,如果任意两个节点都能通过边互相到达,就是连通图。否则会被分成多个连通分量。

有向图里分两种:强连通(任意两点双向可达)和弱连通(把有向边看成无向边后连通)。

类型定义药物图例子
连通图任意节点对之间存在路径完整的小分子结构图
非连通图存在孤立的连通块两个不反应的药物分子放在同一批次里
强连通有向图中任意u→v和v→u都有路径代谢循环中的可逆反应回路
弱连通忽略方向后连通很多信号传导通路
你在做图神经网络池化时,如果图不是连通的,全局池化可能会丢失子结构信息。我曾经用平均池化处理一个含孤立原子的分子图,结果这个原子的特征被整个图的信号淹没了,模型预测完全失效。你可以考虑先用连通分量检测,每个分量单独处理。

实战:用Python构建图

我们用NetworkX快速验证一下这些概念。我一般在处理小样本时才手写邻接矩阵,超过几百个节点就用NetworkX或者PyG。

import networkx as nx
import numpy as np

# 创建无向图
G = nx.Graph()
G.add_edges_from([(0,1), (0,2), (1,2), (1,3), (3,4)])

# 计算度
degrees = dict(G.degree())
print("各节点度:", degrees)

# 邻接矩阵
A = nx.to_numpy_array(G)
print("邻接矩阵:\n", A)

# 连通分量
components = list(nx.connected_components(G))
print("连通分量:", components)
print("是否连通:", nx.is_connected(G))

输出效果:

各节点度: {0: 2, 1: 3, 2: 2, 3: 2, 4: 1}
邻接矩阵:
 [[0. 1. 1. 0. 0.]
 [1. 0. 1. 1. 0.]
 [1. 1. 0. 0. 0.]
 [0. 1. 0. 0. 1.]
 [0. 0. 0. 1. 0.]]
连通分量: [{0, 1, 2, 3, 4}]
是否连通: True

注意节点1的度是3,它连接了0、2、3,在网络里是度最高的。如果这是一个蛋白质交互网络,节点1可能就是关键靶点。

图的存储选择:邻接表 vs 邻接矩阵

我们做药物分子图时,分子通常稀疏,平均度不超过5。这时候邻接表更省空间,邻接矩阵更适合密集图或需要矩阵运算的场景。

存储方式空间复杂度查询边时间适用场景
邻接矩阵O(V²)O(1)稠密图、矩阵运算
邻接表O(V+E)O(deg)稀疏图、药物分子

我个人倾向于用邻接表做特征聚合(比如GCN的消息传递),用邻接矩阵做谱方法(比如ChebNet)。没必要一条路走到黑,工具选对事半功倍。

连通性在药物节点分类中的意义

想象你在给胆固醇分子打标签,如果图不是连通的,意味着分子有独立片段(比如两个不直接相连的环)。直连的原子间可能有化学键约束,而片段之间可能有空间位阻。如果池化时不区分连通分量,模型就会误以为所有原子都能互相影响。

我在做毒性预测时遇到过:一个分子包含长烷基链和苯环,它们通过一个碳原子连接(图是连通的)。但苯环上的电子效应很难通过单键传递到烷基链另一头。这时候只靠图的全局连通是不够的,你得考虑距离或者跳数。嗯,这又是另一个坑,后面讲图核的时候再细聊。