图特征提取基础:图数据表示、邻接矩阵、度矩阵、拉普拉斯矩阵

各位同学好,我是咱们这门课的老赵。今天咱们正式开始第一讲——图特征提取的基础。说实话,这部分内容看起来简单,但我见过不少同学包括早期的我自己,在这上面栽过跟头。你想想看,分子生成领域里,我们面对的每个分子其实都是一张图,怎么把这图变成数学上能算的东西,这就是本讲的精髓。

图数据表示:从分子结构到数学模型

先问大家一个问题:一个分子怎么变成图?

说白了,原子就是节点,化学键就是边。我早期做分子生成项目时,第一步就是把分子结构式转化成图。这件事听起来简单,实际操作有不少坑。

一个标准的图,用数学语言说是 G = (V, E)。其中 V 是节点集合,E 是边集合。在分子场景里,节点带特征——原子类型、电荷、立体化学信息。边也带特征——键级、是否芳香键。

  • 节点 (V):比如 C、N、O、H 等原子。每个节点都可以附带一个特征向量。
  • 边 (E):单键、双键、三键、芳香键。边也可以有方向或权重。

举个具体例子,甲烷(CH₄)的分子图:

节点集合 = {C, H₁, H₂, H₃, H₄}
边集合 = {(C, H₁), (C, H₂), (C, H₃), (C, H₄)}
所有边都是单键,权重统一为 1

嗯,这里要注意:在实际代码实现中,节点顺序很重要。不同的节点顺序会产生不同的矩阵表示,但图本身是一样的。这就是图数据的置换不变性——我当年刚入行时,花了整整一周才把这个逻辑梳理清楚。

邻接矩阵:图的骨架

邻接矩阵是表达图结构最直接的方式。本质上就是个二维表格,行和列都对应节点,单元格里填的是边信息。

对于有 n 个节点的图,邻接矩阵 A 的大小是 n × n:

  • 简单图:A[i][j] = 1 表示节点 i 和 j 之间有边,否则为 0。
  • 带权图:A[i][j] = w,w 是边的权重(比如键级)。
  • 有向图:A[i][j] ≠ A[j][i]。

我之前踩过坑:图里有自环时,邻接矩阵的对角线元素怎么处理?

分子生成中,除非你在模拟特殊反应中间体,一般对角线都设为 0。不过如果你做分子动力学中的某些特殊场景,自环可能是需要的。这种情况我建议看清楚问题再决定。

邻接矩阵有三种常见变体:

类型 元素含义 分子应用场景
简单邻接矩阵 0/1 图论分析、连通性判断
带权邻接矩阵 键级或距离 分子力学、力场计算
多重边邻接矩阵 整数表示边数 共振结构、动态键解析

项目心得:我早期做分子生成时,经常用稀疏矩阵来存邻接矩阵。分子图通常很稀疏——几百个原子,边数远小于全连接。用稠密矩阵存,内存直接炸。建议用 scipy.sparse 或 PyTorch 的稀疏张量。

度矩阵:节点连接数的一览表

度矩阵 D 是个对角矩阵,对角线上 D[i][i] 是节点 i 的度——也就是它连接的边数。

公式很简单:D[i][i] = Σⱼ A[i][j]

计算也直接:把邻接矩阵第 i 行所有非零值加起来,放进 D[i][i]。

拿刚才甲烷的例子,碳原子的度是 4,四个氢原子的度都是 1。度矩阵就是:

碳节点   4    0    0    0    0
H₁       0    1    0    0    0
H₂       0    0    1    0    0
H₃       0    0    0    1    0
H₄       0    0    0    0    1

我早期做分子生成时,经常画出度矩阵来检查图结构对不对。度数太高的节点可能是错误连接——比如一个碳连了 5 个原子出来,那多半是数据问题。

拉普拉斯矩阵:图信号处理的灵魂

拉普拉斯矩阵 L 的定义很简单:L = D - A

但它的意义远不止是个减法。它蕴含了图的谱信息,在分子生成中常用于图卷积、谱聚类、分子构象分析。

拉普拉斯矩阵有三种主要形式,我建议你记清楚区别:

类型 公式 特点
标准拉普拉斯 L = D - A 行和、列和为 0,半正定
对称归一化拉普拉斯 Lsym = I - D-½ A D-½ 特征值在 [0, 2] 区间,用于图卷积网络
随机游走归一化拉普拉斯 Lrw = I - D-1 A 行和为 0,用于随机游走类算法

说到项目经验,我在做图卷积网络时发现,对称归一化拉普拉斯矩阵用起来明显更稳。特征值被限制在 [0, 2] 之间,梯度爆炸的风险小很多。

核心要点:拉普拉斯矩阵的二次型 xᵀLx 可以衡量图信号 x 的平滑度。平滑的信号在相邻节点上值接近。这个性质在分子性质预测、构象生成里非常有用——说白了,相邻原子之间的物理性质不会突变,这就是拉普拉斯矩阵帮我们捕捉的先验知识。

接下来我用一张图帮大家梳理这四个概念的关系:

图特征提取基础:核心逻辑与知识结构 分子图 G = (V, E) 邻接矩阵 A 度矩阵 D 拉普拉斯矩阵 L 节点连接关系 节点度数统计 L = D - A 核心关系与用途 • 从 A 可以快速算出 D:对角线和行 • 从 A 和 D 可以构造 L 的三种形式 • 拉普拉斯矩阵的谱性质用于图卷积 • 度矩阵用于归一化解规模 分子图表示 谱聚类 / GCN 分子性质预测

这张图把咱们讲的四个概念串起来了。分子图是起点,三种矩阵各有所长,最终落到具体的分子生成应用上。

代码示例:怎么在 Python 里计算这些矩阵

理论讲完,咱们上手实际看一下。用 NetworkX 和 NumPy,几行代码就能搞定:

import numpy as np
import networkx as nx

# 构建一个简单的分子图——甲烷
G = nx.Graph()
G.add_nodes_from(['C', 'H1', 'H2', 'H3', 'H4'])
edges = [('C', 'H1'), ('C', 'H2'), ('C', 'H3'), ('C', 'H4')]
G.add_edges_from(edges)

# 获取邻接矩阵
A = nx.adjacency_matrix(G).toarray()
print("邻接矩阵 A:")
print(A)

# 计算度矩阵
degrees = [d for _, d in G.degree()]
D = np.diag(degrees)
print("\n度矩阵 D:")
print(D)

# 计算拉普拉斯矩阵
L = D - A
print("\n拉普拉斯矩阵 L = D - A:")
print(L)

避坑指南:我曾经用上面这段代码跑了上千个分子的数据,发现注意节点顺序很重要。NetworkX 默认按节点添加顺序排列,如果你需要固定顺序,建议用 sorted(G.nodes()) 明确指定。

归一化拉普拉斯矩阵的实现也很直接:

# 对称归一化拉普拉斯 L_sym = I - D^(-1/2) A D^(-1/2)
D_inv_sqrt = np.linalg.inv(np.sqrt(D))
L_sym = np.eye(len(degrees)) - D_inv_sqrt @ A @ D_inv_sqrt
print("\n对称归一化拉普拉斯矩阵 L_sym:")
print(np.round(L_sym, 4))

重要提醒:当某个节点度数为 0(孤立节点)时,D-½ 会除零出错。这种极端情况在分子生成中虽然不多,但处理带残缺结构的分子时确实会遇到。我建议加上 deg = max(1, deg) 的保底处理,反正孤立节点的归一化怎么算都影响不大,关键是不能崩溃。

几种矩阵表示的核心对比

表格总结一下它们的区别和用途,方便你快速查阅:

矩阵 维度 对称性 稀疏性 关键属性 分子应用
邻接矩阵 A n × n 无向图对称 通常稀疏 行和 = 度 图同构检验
度矩阵 D n × n 对角对称 几乎对角 迹 = 2|E| 节点度统计分析
标准拉普拉斯 L n × n 对称 同 A 零空间维数 = 连通分量数 分子团簇分割
对称归一化拉普拉斯 L_sym n × n 对称 同 A 特征值 ∈ [0, 2] 图卷积网络
随机游走归一化拉普拉斯 L_rw n × n 非对称 同 A 行和为 0 扩散过程建模

总结一下本讲的重点:

  • 图是分子的数学化身,节点和边的定义直接影响后续建模质量。
  • 邻接矩阵是最底层的结构信息,分子图通常是稀疏的。
  • 度矩阵虽然简单,但它是归一化操作的基石。
  • 拉普拉斯矩阵是图信号处理的核心工具,三种归一化形式各有适用场景。

我相信这部分基础打牢后,后续讲图神经网络、消息传递、以及最终的分子生成模型时,你会觉得顺手很多。这些矩阵操作,说白了就是图深度学习里的加减乘除,没什么高深的,但用错了地方就会出大问题。