图神经网络 GNN
本页介绍图神经网络(Graph Neural Network, GNN):专门处理图结构数据的神经网络。传统网络(CNN 处理网格图像、RNN/Transformer 处理线性序列)无法直接处理社交网络、分子结构、知识图谱这类”节点 + 边”的不规则拓扑数据,GNN 正是为这类数据而生。
现实世界中大量数据天然是图结构:社交网络里人是节点、关注关系是边;分子里原子是节点、化学键是边;知识图谱里实体是节点、关系是边。这类数据有两个传统网络搞不定的特点:没有固定顺序(图节点没有”第一个""最后一个”之分)、大小可变(一个分子 10 个原子,另一个 100 个原子)。
如果直接把图的节点特征丢给多层感知机(MLP,即普通全连接网络堆叠),模型只能看到每个节点自己的属性,完全忽略了”谁和谁相连”这层关系;如果把图喂给 CNN,又找不到图像那种规则的像素网格;喂给 RNN/Transformer,也无法对节点排出一个自然顺序。GNN 的关键就是把”连接关系”作为一等公民纳入计算。
GNN 的核心思想是消息传递(Message Passing):每个节点起初有自己的特征向量,然后反复做一件事——把自己的特征”广播”给邻居,同时收集邻居广播来的特征,用某种方式聚合(求和/平均/取最大)后更新自己的特征。经过 K 轮消息传递后,每个节点的特征就融合了 K 跳范围内所有邻居的信息。
用人际网络来类比:第一轮,你了解了直接朋友的近况;第二轮,你通过朋友了解了朋友的朋友;第 K 轮,你的信息覆盖了社交圈里 K 度人脉。GNN 让每个节点最终都”知道”自己 K 跳邻域的全貌,这就是它能做节点分类、链路预测、图分类的基础。
感受野(Receptive Field):借鉴自 CNN 的概念——一个节点在第 K 层能”看到”的信息范围,就是它在图中 K 跳的邻域。层数越多,感受野越大;但太大会带来后面要讲的”过度平滑”问题,需要权衡。
消息传递的统一框架
Section titled “消息传递的统一框架”几乎所有现代 GNN(GCN、GAT、GraphSAGE、GIN 等)都可以放进同一个**消息传递神经网络(MPNN)**框架里来理解。一层消息传递可以拆成三步:
- 消息生成(Message):对每条边
(i, j),根据两端节点特征h_i, h_j(可能还有边特征e_ij)计算一条”消息”m_ij = φ(h_i, h_j, e_ij),其中φ通常是一个小型神经网络。 - 邻域聚合(Aggregate):每个节点
i把所有邻居发来的消息用一个置换不变(permutation invariant,即与邻居的输入顺序无关)的算子□合并,得到汇总消息M_i = □_{j∈N(i)} m_ij。常见的□有求和、平均、最大值,或者带权求和。 - 特征更新(Update):用汇总消息更新节点特征,
h_i' = ψ(h_i, M_i),其中ψ一般也是一个神经网络,外加非线性激活。
不同的 GNN 架构,本质上就是给 φ、□、ψ 赋予不同的具体形式。只要聚合算子 □ 对邻居顺序不变,整个网络对图节点的任意重新编号就都是等价的——这正是 GNN 能处理无序图结构的数学根源。
GCN:图卷积网络
Section titled “GCN:图卷积网络”Kipf & Welling 在 2016 年提出的 GCN,可以看作上述框架的一个特例:消息函数是恒等的,聚合方式是”按度数归一化的求和”,更新函数是一个线性变换加 ReLU(一种最常用的非线性激活函数,对负值置零、保留正值)。一层的公式是:
其中各符号的含义:
H是当前所有节点的特征矩阵,形状[N, d],N是节点数、d是特征维度。W是可学习的权重矩阵,形状[d, d'],负责做特征维度的线性变换。Ã = A + I是加了自环(self-loop,节点指向自己的一条边,让节点在聚合时也把自己”当邻居”)的邻接矩阵。D̃是Ã的度矩阵(对角矩阵,对角线元素是每个节点的度数)。D̃^(-1/2) · Ã · D̃^(-1/2)这一步就是对称归一化:度数高的节点会把聚合结果稀释,防止”超级节点”的特征数值爆炸,也让每个邻居的贡献更均衡。σ是非线性激活函数(如 ReLU)。
卷积(Convolution):在 CNN 里,“卷积”指一个小小的卷积核(一组可学习权重,比如 3×3)在图像上滑动、与对应区域的像素做加权求和;在 GNN 里,“图卷积”借用了这个概念——只不过”邻居”不再是固定网格上的像素,而是图里每个节点的邻接节点,权重由度数(或注意力)决定。
GAT:图注意力网络
Section titled “GAT:图注意力网络”GCN 的归一化权重完全由图的拓扑结构(度数)决定,对所有邻居一视同仁。GAT(Graph Attention Network)换了个思路:让模型自己学习每个邻居该占多大权重。具体来说,对节点 i 和邻居 j,用一个可学习的注意力函数算出一个分数 α_ij,再在所有邻居上做 softmax(一种把一组数值压成”和为 1 的概率分布”的操作,让大的值更突出),得到注意力权重,最后做加权求和:
其中 ‖ 表示向量拼接,a 是注意力向量,W 是共享的特征变换矩阵。这样,与当前节点关系更密切的邻居会自动获得更高权重——这与 Transformer 里的注意力机制(Attention,让模型动态决定”该把注意力放在输入的哪一部分”)是同一个思想,只是作用对象从序列位置变成了图中的邻居。
GraphSAGE:归纳式采样聚合
Section titled “GraphSAGE:归纳式采样聚合”GCN 原版在做一层聚合时,要把一个节点的所有邻居都聚合进来,这对百万、上亿节点的大图既慢又占显存。GraphSAGE 的贡献有两点:
- 邻居采样:每个节点每次只固定采样(比如 10 个)邻居来聚合,把”邻居数不定”变成”邻居数固定”,训练复杂度可控。
- 归纳学习(Inductive Learning):训练时不依赖具体是哪个节点,只学一个”给定邻居特征如何聚合”的通用函数。训练好后,哪怕来了训练时从未见过的新节点、新图,只要提供它的邻居特征就能算出嵌入。
归纳 vs 直推(Inductive vs Transductive):直推模型假设训练时全部节点(含待预测的)都在场,只能给”已知节点”做预测;归纳模型学的是通用规则,能给任何新节点做预测。实际业务里图往往是动态增长的,新用户、新商品不断加入,所以归纳能力几乎是工程必需。
GIN:图同构网络
Section titled “GIN:图同构网络”如果用”能区分多少种不同的图结构”来衡量 GNN 的表达能力,理论上有一个上限——Weisfeiler-Leman (WL) 图同构测试。普通的 GCN/GAT 使用求和/平均/注意力聚合,理论上表达力不超过 1-WL 测试,对某些结构上明显不同的图会给出相同的嵌入。GIN(Graph Isomorphism Network)通过使用求和聚合 + 一个可学习的”重要性系数” (1+ε),把自身特征和邻居特征加权融合,理论上达到了与 1-WL 测试同等的最大表达能力。当任务对结构细微差异敏感(如分子图区分)时,GIN 往往比 GCN 更强。
消息传递机制
Section titled “消息传递机制”经过第 1 轮,每个节点的特征已包含 1 跳邻居的信息;经过第 2 轮,包含 2 跳邻居的信息(因为邻居的特征已经包含了它们的邻居)。一般 GNN 堆叠 2~4 层即可——层太多会导致”过度平滑”(所有节点特征趋于相同)。
三种经典 GNN 架构
Section titled “三种经典 GNN 架构”| 架构 | 全称 | 核心创新 |
|---|---|---|
| GCN | Graph Convolutional Network | 图卷积:聚合时按节点度数归一化,类似”每个邻居的发言权按其连接数稀释” |
| GAT | Graph Attention Network | 引入注意力:让模型自动学习”该更关注哪个邻居”,而非均等对待 |
| GraphSAGE | Graph Sample and Aggregate | 为大图/归纳学习设计:每个节点只采样固定数量的邻居来聚合,可处理未见过的图 |
架构之间的关系
Section titled “架构之间的关系”现代实战中,空间方法(直接在节点邻域上做消息传递)已经基本取代了早期的谱方法(借助图的拉普拉斯矩阵在频域上定义卷积)。前者更直观、效率更高,而 GCN 正是谱方法的一阶近似——这是 GCN 论文的重要贡献:把复杂的谱图卷积简化成了一句
D̃^(-1/2)ÃD̃^(-1/2)HW。
概念代码:一个 GCN 层的朴素实现
Section titled “概念代码:一个 GCN 层的朴素实现”下面用 PyTorch 手写一个 GCN 层的核心逻辑(无第三方 GNN 库),展示消息传递的精髓:
import torchimport torch.nn as nn
class GCNLayer(nn.Module): def __init__(self, in_dim, out_dim): super().__init__() self.linear = nn.Linear(in_dim, out_dim) # 特征变换
def forward(self, X, A): # X: 节点特征矩阵 [N, in_dim],N 是节点数 # A: 邻接矩阵 [N, N],A[i][j]=1 表示 i 和 j 之间有边 # 第 1 步:对每个节点的特征做线性变换(类似全连接) H = self.linear(X) # [N, out_dim] # 第 2 步:消息传递 —— 每个节点收集邻居的特征(矩阵乘法实现) out = A @ H # [N, out_dim] # 第 3 步:非线性激活(实际 GCN 还会按度数做归一化) return torch.relu(out)
# 示例:4 个节点、每个节点 3 维特征、隐藏层输出 2 维X = torch.randn(4, 3) # 4 个节点的特征A = torch.tensor([[1,1,1,0], # 邻接矩阵(含自环) [1,1,0,1], [1,0,1,1], [0,1,1,1]], dtype=torch.float32)layer = GCNLayer(3, 2)print(layer(X, A).shape) # torch.Size([4, 2])真实项目用
torch_geometric(PyG)库,它内置了 GCN/GAT/GraphSAGE 等成熟实现,还处理了稀疏矩阵、批处理、图采样等工程细节。上面这段只是为了让你理解”邻接矩阵 × 特征矩阵”这步矩阵乘法就是消息传递的本质。
加上对称归一化的完整 GCN 层
Section titled “加上对称归一化的完整 GCN 层”上面的朴素版省略了 GCN 论文中的关键一步——按度数对称归一化。下面把它补上,让一个 GCN 层在数学上更接近原论文:
import torchimport torch.nn as nn
class GCNLayerNorm(nn.Module): """带对称归一化的 GCN 层(接近 Kipf & Welling 2016 原版)""" def __init__(self, in_dim, out_dim): super().__init__() self.W = nn.Linear(in_dim, out_dim, bias=False)
def forward(self, X, A_hat, D_inv_sqrt): # X: [N, in_dim] 节点特征 # A_hat: [N, N] 加了自环的邻接矩阵 # D_inv_sqrt: [N, N] 对角矩阵 D̃^(-1/2),可在图预处理时一次算好 H = self.W(X) # 线性变换 support = A_hat @ H # 聚合邻居(未归一化) out = D_inv_sqrt @ support @ D_inv_sqrt # 对称归一化 return out # 外层再套激活函数其中 D_inv_sqrt 就是把度数矩阵 D̃ 每个对角元取倒数平方根。对节点 i、邻居 j 而言,归一化系数是 1/sqrt(d_i) · 1/sqrt(d_j),直观上就是”两端连接越多,这条边的权重越被稀释”。
用 PyG 跑一个两分类任务
Section titled “用 PyG 跑一个两分类任务”下面是用 PyG(torch_geometric)在经典数据集 Cora(一个论文引用图,节点是论文、边是引用关系,任务是预测论文的研究领域)上训练两层 GCN 的最小示例:
# pip install torch torch_geometricimport torchimport torch.nn.functional as Ffrom torch_geometric.nn import GCNConvfrom torch_geometric.datasets import Planetoid
dataset = Planetoid(root='/tmp/Cora', name='Cora')data = dataset[0] # 单张图,含特征、邻接、标签、训练/验证/测试掩码
class GCN(torch.nn.Module): def __init__(self, in_dim, hidden, num_classes): super().__init__() self.conv1 = GCNConv(in_dim, hidden) self.conv2 = GCNConv(hidden, num_classes)
def forward(self, data): x, edge_index = data.x, data.edge_index x = F.relu(self.conv1(x, edge_index)) # 第 1 层 + 激活 x = F.dropout(x, p=0.5, training=self.training) # Dropout 防过拟合 return self.conv2(x, edge_index) # 第 2 层输出 logits
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')model = GCN(dataset.num_features, 16, dataset.num_classes).to(device)data = data.to(device)opt = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
model.train()for epoch in range(200): opt.zero_grad() out = model(data) loss = F.cross_entropy(out[data.train_mask], data.y[data.train_mask]) loss.backward() opt.step()
model.eval()pred = model(data).argmax(dim=1)acc = (pred[data.test_mask] == data.y[data.test_mask]).float().mean()print(f"测试准确率: {acc:.4f}") # 通常在 80% 以上这段代码完整覆盖了”数据加载 → 建模型 → 训练循环 → 评估”四步,是 GNN 入门最经典的”hello world”。
- 层数不要太多:2~4 层就够。GNN 的”过度平滑”(over-smoothing)问题比 CNN 严重得多——堆太多层后所有节点的嵌入会变得几乎相同,失去区分能力。缓解办法包括:残差连接(ResNet 风格地把输入直接加到输出上)、DropEdge(每轮随机丢弃一部分边,类似 Dropout 思路)、以及用归一化层稳定训练。
- 邻接矩阵归一化:度数高的节点(连接很多邻居)如果不归一化,聚合后的特征数值会很大。GCN 用对称归一化(
D̃^(-1/2) Ã D̃^(-1/2)),让每个节点的贡献更均衡。**批量归一化(Batch Normalization,一种按批次对激活值做零均值、单位方差归一化的技术,能让深层网络更稳定、收敛更快)**在 GNN 里也常用,一般放在每层消息传递之后。 - 大图要用采样:百万节点的图无法把整个邻接矩阵塞进显存。GraphSAGE、Cluster-GCN(把大图划成若干子图簇,每次在小簇上训练)、GraphSAINT(按一定策略采样子图作为训练样本)等方法通过子图采样来训练。
- 特征工程仍重要:节点初始特征的质量很关键。社交网络可用用户画像,知识图谱可用实体 embedding(把离散实体映射成稠密向量的过程),分子图用原子类型 one-hot(独热编码,把类别用一个仅一位为 1 的向量表示)。
- 归纳 vs 直推:GraphSAGE 是归纳(inductive)的——训练好后能处理训练时没见过的新节点;GCN 原版是直推(transductive)的——所有节点训练时就要在场。实际应用大多需要归纳能力。
- 注意梯度爆炸/消失:GNN 层与层之间是”特征相乘 + 矩阵相乘”叠加,层数多了同样会有梯度问题。除了归一化层,用 ReLU/LeakyReLU 这类不易饱和的激活、配合合理的学习率和权重衰减(weight decay,在损失里对大权重施加惩罚,抑制过拟合)也是标配。
- 边特征要不要用:很多图(知识图谱、分子图)的边上携带重要信息(关系类型、化学键类型)。此时应选择支持边特征的模型,如 Edge-conditioned GCN、Relational Graph Convolutional Network (R-GCN)(为不同关系类型各学一套权重)。
- 药物发现(分子图):把分子当作图(原子=节点、化学键=边),用 GNN 预测分子的毒性、溶解度、药物活性。DeepMind 的 AlphaFold 2 用结构模块(含等变图网络思想)来预测蛋白质结构;2024 年的 AlphaFold 3 进一步扩展到蛋白质与配体、核酸等复合物的结构预测,几何/等变图网络是该方向的核心工具之一。这是 AI 制药的核心方法之一。
- 社交网络分析:节点分类(预测用户兴趣标签)、社区发现(识别紧密群体)、影响力传播(预测信息扩散路径)。Facebook、Twitter 的反垃圾、推荐都用到 GNN。
- 推荐系统:把”用户—物品”交互建成二部图,GNN 学习用户和物品的嵌入来做协同过滤。Pinterest 的 PinSage 用 GraphSAGE 做了数十亿节点的推荐。
- 知识图谱补全:给定已有实体和关系,预测缺失的三元组(头实体, 关系, 尾实体),用于知识图谱的自动扩充和问答系统。R-GCN、CompGCN 等是常用模型。
- 交通网络:城市路网是图(路口=节点、道路=边),GNN 预测各路段的流量、行程时间,用于导航和智能交通调度。
- 物理模拟:用粒子系统建图(每个粒子是节点),GNN 模拟流体、布料等物理过程(DeepMind 的 Graph Network-based Simulators)。
- 网络安全与欺诈检测:把账号、IP、设备之间的交互建成图,GNN 能发现跨多个节点的欺诈团伙——这类异常往往”单看每个节点都正常,但连接模式可疑”,正是图结构的强项。
典型类库与工具
Section titled “典型类库与工具”| 类库 | 语言 | 说明 |
|---|---|---|
| PyTorch Geometric (PyG) | Python | PyTorch 生态最主流的 GNN 库,内置 GCN/GAT/GraphSAGE 等模型与常用数据集 |
| DGL (Deep Graph Library) | Python | 框架无关的图深度学习库,同时支持 PyTorch / TensorFlow / MXNet |
| GraphGym (PyG 内置) | Python | 快速 GNN 实验平台,一键配置跑各种 GNN 架构对比 |
| Jraph | Python | JAX 生态的轻量 GNN 库,DeepMind 常用,适合做研究原型 |
| StellarGraph | Python | 面向图机器学习的高层库,支持 GNN 和传统图算法 |
| NetworkX | Python | 图分析与操作基础库,常用于数据预处理和可视化(非深度学习) |
| 术语 | 英文 | 解释 |
|---|---|---|
| 图神经网络 | Graph Neural Network (GNN) | 处理图结构数据的神经网络总称 |
| 消息传递 | Message Passing | 节点间交换并聚合特征的机制,GNN 的核心算子 |
| 邻接矩阵 | Adjacency Matrix | 描述图中节点连接关系的矩阵,A[i][j]=1 表示有边 |
| 度 | Degree | 一个节点连接的边数(含自环时加 1) |
| 图卷积 | Graph Convolution | GCN 中的聚合操作,按邻居度数归一化后融合特征 |
| 自环 | Self-loop | 节点指向自己的一条边,聚合时让节点也”当自己的邻居” |
| 对称归一化 | Symmetric Normalization | 用 D̃^(-1/2)ÃD̃^(-1/2) 让每个邻居的贡献按两端度数加权 |
| 节点分类 | Node Classification | 预测图中节点的类别标签 |
| 链路预测 | Link Prediction | 预测图中两个节点之间是否存在(或将存在)边 |
| 图分类 | Graph Classification | 把整个图作为输入预测一个类别,如分子毒性预测 |
| 感受野 | Receptive Field | 一个节点在某层能”看到”的信息范围,K 层覆盖 K 跳邻域 |
| 过度平滑 | Over-smoothing | GNN 层数过多时所有节点嵌入趋于相同的现象 |
| 注意力机制 | Attention Mechanism | 让模型动态决定”该把注意力放在输入的哪一部分”的机制 |
| 归纳学习 | Inductive Learning | 能处理训练时未见过的节点或图的能力 |
| 直推学习 | Transductive Learning | 训练时所有节点(含待预测的)均在场的学习方式 |
| 图同构 | Graph Isomorphism | 两张图是否结构完全相同(节点标签无关)的问题 |
| WL 测试 | Weisfeiler-Leman Test | 判断图同构的经典启发式算法,也是 GNN 表达力的理论上界 |
| 嵌入 | Embedding | 把离散对象(节点、词等)映射成稠密向量 |
| Dropout | Dropout | 训练时随机丢弃一部分神经元/边,抑制过拟合 |
2025-2026 前沿进展
Section titled “2025-2026 前沿进展”说明:本节基于公开研究趋势整理,旨在帮助读者把握方向。具体论文的”最新”请以发表时间为准,建议在 arXiv 等平台检索关键词核实。
- Graph Transformer 成为主流选项:把 Transformer 的全局注意力直接搬到图上——让每个节点”看到”图里所有节点(而非只是局部邻居),并通过位置编码(Positional Encoding,给每个节点附加上表示其在图中结构位置的向量,弥补 Transformer 本身没有图结构感知能力的缺陷,常用随机游走或拉普拉斯特征向量导出)注入结构信息。代表工作有 Graphormer、GraphGPS、SAN。它们在分子预测、小图分类等任务上经常超越传统消息传递 GNN,代价是计算量随节点数平方增长,因此多用于中小图。
- 图基础模型(Graph Foundation Model):借鉴 LLM 的思路,研究者尝试在多种图、多种任务上预训练一个通用大模型,做零样本/少样本迁移。难点在于图的”形态”千差万别(社交图、分子图、知识图谱结构差异巨大),不像文本有统一的 token 序列。代表方向包括用统一消息传递 + 任务提示(prompt)来泛化到新图,以及在标准 benchmark(如 OGB,Open Graph Benchmark)上的持续刷新。
- GNN 与 LLM 融合:大语言模型(LLM)擅长文本推理但不天然理解图结构,GNN 恰好相反。二者结合形成新范式:用 GNN 编码图结构、用 LLM 编码节点上的文本属性(如论文标题、商品描述),再对齐两者的嵌入;或者让 LLM 把图”翻译”成自然语言描述来做推理。这条路线(如 GraphGPT、GraphLLM 等)在知识图谱问答、图推理任务上展现出潜力。
- 等变 / 几何图网络(Equivariant GNN):在分子建模、材料科学中,物理定律对旋转、平移、置换具有不变性。等变 GNN(如 EGNN、SE(3)-Transformer、PaiNN)在设计上保证”输入旋转 → 输出也跟着旋转”,从而把物理对称性内置进网络,显著提升在小分子数据上的样本效率。这是 AlphaFold 系列结构模块的理论基础。
- 扩散模型在图上的应用:把 扩散模型从图像/连续空间扩展到离散的图结构,用于图的生成(从头设计新分子、新蛋白质结构)和图数据的去噪。GraphDiff、EDM(Equilibriun Diffusion Model)等代表了这一方向。
- 缓解过度平滑与深层化:研究者持续探索如何把 GNN 做深(数十层甚至上百层)而不塌缩,思路包括残差/稠密连接、可学习的聚合权重、以及基于能量的 GNN 框架(如 GRAND,把 GNN 看作图上的扩散微分方程离散化)。这为在大图、长程依赖任务上的应用打开空间。
- 子图 GNN 与高阶表达力:为突破 1-WL 的理论上界,子图 GNN(每个节点看自己周围的子图结构)和高阶 Weisfeiler-Leman 模型(2-WL、3-WL)提供更强的结构区分能力,代价是计算开销上升,多用于结构敏感的任务(如分子活性预测中的立体异构体区分)。
- GCN 奠基论文:Kipf & Welling (2016) “Semi-Supervised Classification with Graph Convolutional Networks”——用谱图卷积的一阶近似推导出 GCN,是目前最广为引用的 GNN 工作。
- GAT:Veličković et al. (2017) “Graph Attention Networks”——把注意力机制(见 注意力机制)引入图聚合。
- GraphSAGE:Hamilton et al. (2017) “Inductive Representation Learning on Large Graphs”——采样 + 归纳学习,让 GNN 能扩展到大规模动态图。
- GIN:Xu et al. (2018) “How Powerful are Graph Neural Networks?”——从 WL 同构测试角度分析 GNN 表达力,提出 GIN。
- Graph Transformer 综述:可检索 “Graph Transformer survey 2023/2024”,了解 Graphormer、GraphGPS 等如何把注意力机制与图结构结合。
- 几何深度学习:Bronstein et al. (2021) “Geometric Deep Learning: Grids, Groups, Graphs, Geodesics, and Gauges”——把 GNN 放进更宏大的”几何/对称性”统一框架,是理解等变 GNN 的思想源头。
- 深度学习架构谱系的整体背景见 深度学习概览;消息传递的思想与卷积、注意力同属”聚合邻域信息”的范式,可对比 卷积神经网络 CNN。