Skip to content

图神经网络 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 跳的邻域。层数越多,感受野越大;但太大会带来后面要讲的”过度平滑”问题,需要权衡。

几乎所有现代 GNN(GCN、GAT、GraphSAGE、GIN 等)都可以放进同一个**消息传递神经网络(MPNN)**框架里来理解。一层消息传递可以拆成三步:

  1. 消息生成(Message):对每条边 (i, j),根据两端节点特征 h_i, h_j(可能还有边特征 e_ij)计算一条”消息” m_ij = φ(h_i, h_j, e_ij),其中 φ 通常是一个小型神经网络。
  2. 邻域聚合(Aggregate):每个节点 i 把所有邻居发来的消息用一个置换不变(permutation invariant,即与邻居的输入顺序无关)的算子 □ 合并,得到汇总消息 M_i = □_{j∈N(i)} m_ij。常见的 □ 有求和、平均、最大值,或者带权求和。
  3. 特征更新(Update):用汇总消息更新节点特征,h_i' = ψ(h_i, M_i),其中 ψ 一般也是一个神经网络,外加非线性激活。

不同的 GNN 架构,本质上就是给 φ、□、ψ 赋予不同的具体形式。只要聚合算子 □ 对邻居顺序不变,整个网络对图节点的任意重新编号就都是等价的——这正是 GNN 能处理无序图结构的数学根源。

Kipf & Welling 在 2016 年提出的 GCN,可以看作上述框架的一个特例:消息函数是恒等的,聚合方式是”按度数归一化的求和”,更新函数是一个线性变换加 ReLU(一种最常用的非线性激活函数,对负值置零、保留正值)。一层的公式是:

H′=σ(D~−1/2⋅A~⋅D~−1/2⋅H⋅W)H' = \sigma(\tilde{D}^{-1/2} \cdot \tilde{A} \cdot \tilde{D}^{-1/2} \cdot H \cdot W)

其中各符号的含义:

  • 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 里,“图卷积”借用了这个概念——只不过”邻居”不再是固定网格上的像素,而是图里每个节点的邻接节点,权重由度数(或注意力)决定。

GCN 的归一化权重完全由图的拓扑结构(度数)决定,对所有邻居一视同仁。GAT(Graph Attention Network)换了个思路:让模型自己学习每个邻居该占多大权重。具体来说,对节点 i 和邻居 j,用一个可学习的注意力函数算出一个分数 α_ij,再在所有邻居上做 softmax(一种把一组数值压成”和为 1 的概率分布”的操作,让大的值更突出),得到注意力权重,最后做加权求和:

αij=softmaxj(LeakyReLU(aT⋅[Whi∥Whj]))hi′=σ(∑j∈N(i)αij⋅Whj)\alpha_{ij} = \text{softmax}_j\left(\text{LeakyReLU}\left(a^T \cdot [W h_i \| W h_j]\right)\right) \\ h_i' = \sigma\left(\sum_{j \in N(i)} \alpha_{ij} \cdot W h_j\right)

其中 ‖ 表示向量拼接,a 是注意力向量,W 是共享的特征变换矩阵。这样,与当前节点关系更密切的邻居会自动获得更高权重——这与 Transformer 里的注意力机制(Attention,让模型动态决定”该把注意力放在输入的哪一部分”)是同一个思想,只是作用对象从序列位置变成了图中的邻居。

GCN 原版在做一层聚合时,要把一个节点的所有邻居都聚合进来,这对百万、上亿节点的大图既慢又占显存。GraphSAGE 的贡献有两点:

  • 邻居采样:每个节点每次只固定采样(比如 10 个)邻居来聚合,把”邻居数不定”变成”邻居数固定”,训练复杂度可控。
  • 归纳学习(Inductive Learning):训练时不依赖具体是哪个节点,只学一个”给定邻居特征如何聚合”的通用函数。训练好后,哪怕来了训练时从未见过的新节点、新图,只要提供它的邻居特征就能算出嵌入。

归纳 vs 直推(Inductive vs Transductive):直推模型假设训练时全部节点(含待预测的)都在场,只能给”已知节点”做预测;归纳模型学的是通用规则,能给任何新节点做预测。实际业务里图往往是动态增长的,新用户、新商品不断加入,所以归纳能力几乎是工程必需。

如果用”能区分多少种不同的图结构”来衡量 GNN 的表达能力,理论上有一个上限——Weisfeiler-Leman (WL) 图同构测试。普通的 GCN/GAT 使用求和/平均/注意力聚合,理论上表达力不超过 1-WL 测试,对某些结构上明显不同的图会给出相同的嵌入。GIN(Graph Isomorphism Network)通过使用求和聚合 + 一个可学习的”重要性系数” (1+ε),把自身特征和邻居特征加权融合,理论上达到了与 1-WL 测试同等的最大表达能力。当任务对结构细微差异敏感(如分子图区分)时,GIN 往往比 GCN 更强。

经过第 1 轮,每个节点的特征已包含 1 跳邻居的信息;经过第 2 轮,包含 2 跳邻居的信息(因为邻居的特征已经包含了它们的邻居)。一般 GNN 堆叠 2~4 层即可——层太多会导致”过度平滑”(所有节点特征趋于相同)。

架构全称核心创新
GCNGraph Convolutional Network图卷积:聚合时按节点度数归一化,类似”每个邻居的发言权按其连接数稀释”
GATGraph Attention Network引入注意力:让模型自动学习”该更关注哪个邻居”,而非均等对待
GraphSAGEGraph Sample and Aggregate为大图/归纳学习设计:每个节点只采样固定数量的邻居来聚合,可处理未见过的图

现代实战中,空间方法(直接在节点邻域上做消息传递)已经基本取代了早期的谱方法(借助图的拉普拉斯矩阵在频域上定义卷积)。前者更直观、效率更高,而 GCN 正是谱方法的一阶近似——这是 GCN 论文的重要贡献:把复杂的谱图卷积简化成了一句 D̃^(-1/2)ÃD̃^(-1/2)HW。

概念代码:一个 GCN 层的朴素实现

Section titled “概念代码:一个 GCN 层的朴素实现”

下面用 PyTorch 手写一个 GCN 层的核心逻辑(无第三方 GNN 库),展示消息传递的精髓:

import torch
import 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 论文中的关键一步——按度数对称归一化。下面把它补上,让一个 GCN 层在数学上更接近原论文:

import torch
import 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(torch_geometric)在经典数据集 Cora(一个论文引用图,节点是论文、边是引用关系,任务是预测论文的研究领域)上训练两层 GCN 的最小示例:

# pip install torch torch_geometric
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from 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 能发现跨多个节点的欺诈团伙——这类异常往往”单看每个节点都正常,但连接模式可疑”,正是图结构的强项。
类库语言说明
PyTorch Geometric (PyG)PythonPyTorch 生态最主流的 GNN 库,内置 GCN/GAT/GraphSAGE 等模型与常用数据集
DGL (Deep Graph Library)Python框架无关的图深度学习库,同时支持 PyTorch / TensorFlow / MXNet
GraphGym (PyG 内置)Python快速 GNN 实验平台,一键配置跑各种 GNN 架构对比
JraphPythonJAX 生态的轻量 GNN 库,DeepMind 常用,适合做研究原型
StellarGraphPython面向图机器学习的高层库,支持 GNN 和传统图算法
NetworkXPython图分析与操作基础库,常用于数据预处理和可视化(非深度学习)
术语英文解释
图神经网络Graph Neural Network (GNN)处理图结构数据的神经网络总称
消息传递Message Passing节点间交换并聚合特征的机制,GNN 的核心算子
邻接矩阵Adjacency Matrix描述图中节点连接关系的矩阵,A[i][j]=1 表示有边
度Degree一个节点连接的边数(含自环时加 1)
图卷积Graph ConvolutionGCN 中的聚合操作,按邻居度数归一化后融合特征
自环Self-loop节点指向自己的一条边,聚合时让节点也”当自己的邻居”
对称归一化Symmetric Normalization用 D̃^(-1/2)ÃD̃^(-1/2) 让每个邻居的贡献按两端度数加权
节点分类Node Classification预测图中节点的类别标签
链路预测Link Prediction预测图中两个节点之间是否存在(或将存在)边
图分类Graph Classification把整个图作为输入预测一个类别,如分子毒性预测
感受野Receptive Field一个节点在某层能”看到”的信息范围,K 层覆盖 K 跳邻域
过度平滑Over-smoothingGNN 层数过多时所有节点嵌入趋于相同的现象
注意力机制Attention Mechanism让模型动态决定”该把注意力放在输入的哪一部分”的机制
归纳学习Inductive Learning能处理训练时未见过的节点或图的能力
直推学习Transductive Learning训练时所有节点(含待预测的)均在场的学习方式
图同构Graph Isomorphism两张图是否结构完全相同(节点标签无关)的问题
WL 测试Weisfeiler-Leman Test判断图同构的经典启发式算法,也是 GNN 表达力的理论上界
嵌入Embedding把离散对象(节点、词等)映射成稠密向量
DropoutDropout训练时随机丢弃一部分神经元/边,抑制过拟合

说明:本节基于公开研究趋势整理,旨在帮助读者把握方向。具体论文的”最新”请以发表时间为准,建议在 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。