第三章 图卷积网络(GCN)详解:消息传递机制、谱域与空域
好,咱们进入正题。GCN 这东西,说白了就是让图结构上的节点学会“社交”。每个节点不光看自己,还得看邻居在干啥。我刚开始接触这个领域时,也觉得不就是把卷积搬到了图上嘛。后来才明白,这里面的门道可深了。
3.1 消息传递范式——GCN 的灵魂
你想想看,图像卷积是拿一个固定大小的窗口滑过像素。图呢?邻居数量不固定,结构也没规则。怎么办?学术界想了个办法——消息传递。
消息传递分三步走:
- 消息生成:每个节点把自己的特征包装成“消息”。
- 消息聚合:邻居的消息汇到一起,用求和、平均或最大值啥的。
- 特征更新:节点结合自己的旧特征和聚合来的邻居消息,算出新特征。
我在项目中遇到过最坑的事:有人直接把邻居消息求和,结果度大的节点特征值爆炸,训都训不动。后来加了个归一化系数,才稳下来。
核心公式(简化版):
H^(l+1) = σ( D̂^(-1/2) · Â · D̂^(-1/2) · H^(l) · W^(l) )
其中 Â = A + I(加自环),D̂ 是度矩阵。这公式看着复杂,实际就是在做“归一化的邻居平均”。
我建议你把消息传递想象成“小区广播”。每家(节点)喊出自己的特征,邻居听到后汇总,再结合自家情况做决策。这样好理解多了。
3.2 谱域 vs 空域——两大派系
GCN 发展过程中形成了两条技术路线。一条从傅里叶变换切入,另一条直接在图上操作。我给你捋一捋。
| 对比维度 | 谱域方法(Spectral) | 空域方法(Spatial) |
|---|---|---|
| 理论基础 | 图傅里叶变换、拉普拉斯矩阵 | 消息传递、局部聚集 |
| 代表模型 | ChebNet, GCN(Kipf版) | GraphSAGE, GAT, GIN |
| 计算效率 | 需做特征分解,图大时慢 | 适合大规模图(采样方式) |
| 局限性 | 图结构不能变(转导学习) | 需要设计聚合函数 |
我记得刚读论文时,谱域那套数学把我整懵了好久。但实际写代码时发现,Kipf 那篇 GCN 其实把谱域简化成了空域形式——只取一阶切比雪夫近似。所以你现在用的 GCN 基本都是“谱域出身、空域长相”。
曾经有个朋友把谱域 GCN 直接用在动态图上(图结构随时间变化),结果模型崩了。原因:谱域方法依赖固定的拉普拉斯矩阵,图一变,谱也跟着变,之前的参数全白训了。所以啊,动态图场景优先考虑空域方法。
3.3 GCN 的消息传递细节——逐层拆解
咱们用一个分子图举例。假设每个原子是节点,化学键是边。原子特征可以是原子序数、手性、电荷啥的。
一层 GCN 干的事:
- 每个原子把自己的特征 × 权重矩阵,得到“消息”。
- 再从邻居原子那里收集消息,取平均(带归一化)。
- 经过 ReLU 激活,得到该层输出。
我在做分子性质预测时,发现两层 GCN 效果最好。一层只能看直接邻居,两层就能看到“邻居的邻居”。再深反而过平滑——所有节点特征变得一模一样,丧失了区分度。
两层 GCN 的伪代码(PyTorch 风格):
class GCNLayer(nn.Module):
def __init__(self, in_dim, out_dim):
super().__init__()
self.W = nn.Linear(in_dim, out_dim)
def forward(self, x, adj_norm):
# x: 节点特征 [N, in_dim]
# adj_norm: 归一化邻接矩阵 [N, N]
out = adj_norm @ x # 邻居消息聚合
out = self.W(out) # 线性变换
return F.relu(out) # 非线性激活
实际实现时别忘了加自环。我踩过坑:不加自环的话,节点自己的特征在聚合时完全丢失,模型学不到自己的信息。
3.4 从分子生成角度看 GCN
生成分子,通常不是直接造出完整的图。而是逐原子、逐键地生成。GCN 在这里扮演“特征提取器”的角色——把当前部分分子的拓扑信息编码成向量,供下一步决策用。比如,决定下一个原子该连到哪个位置。
常见的分子生成流程:
- 用 GCN 编码当前部分分子图 → 得到每个节点的隐向量。
- 用 readout(如全局池化)得到图级别向量。
- 拼接节点向量和图向量,预测下一步动作(加原子、加键、结束)。
我参与过一个药物分子生成项目,当时在编码器里用了 3 层 GCN,每层 64 维。结果生成出来的分子有效性只有 30% 出头。后来把层数减到 2 层,维度降到 32,有效性反而提升到 65%。你说怪不怪?其实就是过深过宽导致过拟合或过平滑。嗯,这个经验后来我一直用。
3.5 GCN 的局限与改进思路
GCN 虽然经典,但有几个硬伤:
- 同质性假设:GCN 天然倾向于认为邻居节点应该相似。但对于异配图(如分子中不同原子性质差异很大),这个假设不成立。
- 表达能力有限:1-WL 测试表明,普通 GCN 无法区分某些非同构图(比如两个完全不同的分子却有相同的 GCN 输出)。
- 过平滑问题:层数一多(>4 层),所有节点特征趋同。
怎么破?我常用的招数:
- 用 GAT(图注意力网络)给每个邻居学个权重,而不是等权平均。
- 加跳跃连接(如 JK-Net),保留浅层信息。
- 用 GIN(图同构网络)提升表达能力。
曾经有个项目,我们要预测分子毒性。GCN 训出来 AUC 只有 0.78,换成 GIN 直接干到 0.89。差别就在 GIN 用了 sum 聚合而不是 mean,能更好地捕获不同邻居数量的差异。所以啊,选模型别只看名气,得对症下药。
3.6 本章知识结构图
下面这张图汇总了 GCN 的核心脉络,从消息传递到谱域/空域,再到分子生成应用。你看一眼就能回忆起来。
我一般用这个结构图给学生讲 GCN。先讲消息传递,再讲谱域空域区别,最后落到分子生成。节奏紧凑,不容易跑偏。你自己讲课时也可以照着这个思路来。