图的基本概念:节点、边、度、邻接矩阵、图的连通性
各位好,今天我们来聊聊图——不是那种柱状折线图,而是由节点和边构成的数学结构。说实话,我在做药物分子性质预测时天天跟图打交道。分子里的原子就是节点,化学键就是边。不理解这些基础,后面的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个节点的无向图,每个节点标注了度,右侧是它的邻接矩阵。
图的连通性:整体与子结构
连通性描述图是否“抱成一团”。无向图中,如果任意两个节点都能通过边互相到达,就是连通图。否则会被分成多个连通分量。
有向图里分两种:强连通(任意两点双向可达)和弱连通(把有向边看成无向边后连通)。
| 类型 | 定义 | 药物图例子 |
|---|---|---|
| 连通图 | 任意节点对之间存在路径 | 完整的小分子结构图 |
| 非连通图 | 存在孤立的连通块 | 两个不反应的药物分子放在同一批次里 |
| 强连通 | 有向图中任意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)。没必要一条路走到黑,工具选对事半功倍。
连通性在药物节点分类中的意义
想象你在给胆固醇分子打标签,如果图不是连通的,意味着分子有独立片段(比如两个不直接相连的环)。直连的原子间可能有化学键约束,而片段之间可能有空间位阻。如果池化时不区分连通分量,模型就会误以为所有原子都能互相影响。
我在做毒性预测时遇到过:一个分子包含长烷基链和苯环,它们通过一个碳原子连接(图是连通的)。但苯环上的电子效应很难通过单键传递到烷基链另一头。这时候只靠图的全局连通是不够的,你得考虑距离或者跳数。嗯,这又是另一个坑,后面讲图核的时候再细聊。