GCN 2017 — 把卷积搬到图结构上的最简版本
是什么
GCN(Graph Convolutional Network)是一种让神经网络处理”图结构”数据的方法。
日常类比:你想猜一个学生的兴趣,不光看他自己填的问卷,还看他朋友圈里的人填了什么——朋友越像,他就越可能像。GCN 把这件事写成数学:每一层,每个节点把自己和邻居的特征做加权平均,再过一道变换。
经典 CNN 处理的是网格——图像是二维网格、文本是一维序列,邻居是谁很清楚。但社交网络、引用图、分子这些数据没有规则邻居,每个节点的度数不一样,连接也乱。GCN 用一条简化到极致的公式解决了这个问题。
为什么重要
不理解 GCN,下面这些事都没法解释:
- 为什么 2017 年之后图神经网络(GNN)会突然”爆发”——之前 Bruna 2013 的谱方法已经能做,但太慢太难训
- 为什么社交推荐、药物发现、知识图谱补全都开始用同一套思路
- 为什么 PyTorch Geometric / DGL 这些库的核心 API 长得都像 GCN 一层
- 为什么 LLM 时代的 GraphRAG 也要先把文档建成图再”跑一遍 GCN 思路”做检索
GCN 的贡献不是”第一个”,而是简化到能被普通工程师 30 行 PyTorch 复现——这才点燃了 GNN 整条赛道。
核心要点
GCN 一层的公式(看不懂没关系,下面拆开讲):
H^(l+1) = σ( D̃^(-1/2) · Ã · D̃^(-1/2) · H^(l) · W^(l) )把符号翻译成人话:
- Ã = A + I:A 是邻接矩阵(谁连谁),加单位矩阵 I 等于”给每个节点连一条到自己的边”。不加自环,节点会丢掉自己的特征。
- D̃^(-1/2) Ã D̃^(-1/2):按度归一化。度大的节点(社交达人)权重压低,度小的节点权重抬高。否则”大 V”会主导整张图。
- H^(l):上一层的节点特征矩阵(每行一个节点)。第 0 层就是输入特征。
- W^(l):可训练的线性变换权重(和普通神经网络一样)。
- σ:非线性激活,比如 ReLU。
一句话总结:邻居加权平均 → 线性变换 → 非线性。两层这种结构堆起来,就够在 Cora 引用网络上把节点分类做到 SOTA。
实践案例
案例 1:用 GCN 给 Cora 论文分类
Cora 数据集:2708 篇论文(节点)、5429 条引用关系(边)、每篇有 1433 维词袋特征、7 个类别。
任务:只标注 140 篇(5%),让模型把另外 1000 篇分类。
# 伪代码(概念演示)import torch.nn as nn
class GCN(nn.Module): def __init__(self, n_feat, n_hid, n_class): super().__init__() self.W1 = nn.Linear(n_feat, n_hid) self.W2 = nn.Linear(n_hid, n_class) def forward(self, X, A_norm): # A_norm 已经做完 D̃^(-1/2) Ã D̃^(-1/2) H = torch.relu(A_norm @ self.W1(X)) H = A_norm @ self.W2(H) return H # 用 cross_entropy 就能训关键观察:只有 30 行的模型,Cora 准确率 81.5%,比之前的 Planetoid(75.7%)高一截。
案例 2:从谱方法简化到一阶近似
GCN 不是凭空冒出来的。论文从谱图卷积推导:
- 图傅里叶变换需要算拉普拉斯矩阵的特征分解,O(n³) 太慢
- Defferrard 2016(ChebNet)用 K 阶 Chebyshev 多项式逼近,省掉特征分解
- GCN 取 K=1(只看一跳邻居) + 重归一化 trick
最后剩下的就是开头那条公式。简化才是贡献——把谱方法落地到能用。
案例 3:堆深就翻车(oversmoothing)
直觉上”层数越多越好”,GCN 不成立:
| 层数 | Cora 准确率 |
|---|---|
| 2 | 81.5% |
| 3 | 79.0% |
| 5 | 70.0% |
| 10 | <40% |
(数字为示意趋势,不同实现细节会有差异)。每层都做”邻居平均”,多次平均后所有节点特征趋同——这就是 oversmoothing。后续工作(DropEdge / GCNII / PairNorm)专门修这个洞。
踩过的坑
-
忘加自环 A + I:节点把自己的特征丢了,只剩邻居的”投票”,效果直接掉 5-10 个点。
-
归一化方式选错:行归一化(D^-1 A)比对称归一化(D^-1/2 A D^-1/2)效果差,论文里有消融。原因是非对称矩阵特征值分布更不稳定。
-
以为能 inductive:原始 GCN 是 transductive 的——训练时整张图(含测试节点的连接)都要在内存里。要做 inductive(新节点加进来)得用 GraphSAGE 或 FastGCN。
-
大图放不下:Cora 才 2708 个节点,full-batch 没问题。换到 OGB 几百万节点,显存直接炸。需要 mini-batch 邻居采样。
-
一视同仁的邻居:所有邻居权重只按度归一化,没法表达”这个邻居比那个重要”。GAT 用 attention 修了这点。
适用 vs 不适用场景
适用:
- 节点分类(半监督,标签稀疏):引用网络、社交网络、蛋白质相互作用
- 图相对静态(训练和测试时图结构差不多)
- 中小规模图(百万节点以下)
- 想要一个简单基线——再复杂的 GNN 也常被 GCN 比下来
不适用:
- 大规模动态图(节点/边一直变)→ 用 GraphSAGE / PinSAGE 采样版
- 需要区分邻居重要性 → 用 GAT
- 异质图(多种节点/边类型)→ 用 R-GCN / HGT
- 长程依赖(要走 10 跳才相关)→ GCN oversmoothing;考虑 Graph Transformer
历史小故事(可跳过)
- 2008:Scarselli 提出最早的 GNN,用迭代到不动点训练,难训也慢
- 2013:Bruna 把谱方法引进图卷积,理论漂亮但 O(n³) 太贵
- 2016 Sept:Kipf(博士在读,导师 Welling)把 ChebNet 一阶截断 + 重归一化 trick 写成 ICLR 投稿。代码挂 GitHub,30 行 TensorFlow
- 2017 ICLR:录用,引用迅速破万。Kipf 同年做了 R-GCN(关系图)、VGAE(图自编码器),博士论文成了一系列经典
- 2018-:GraphSAGE / GAT / GIN 接力,GNN 成 ML 子领域
- 2024-:LLM 时代回潮,GraphRAG 把图结构搬进检索增强生成
学到什么
- 大胆简化:从复杂方法(谱卷积)狠狠砍到能跑(一跳邻居 + 一阶近似)——简化本身就是贡献
- 归一化决定能不能训:邻居加权那一步对称归一化不是装饰,是稳定性保证
- 深度不是越深越好:消息传递类模型有 oversmoothing 这道天花板
- 半监督的甜区:图结构本身就是”伪标签”——通过邻居把少量标签传播出去,这是 GCN 在 5% 标签场景碾压全监督模型的根本原因
- 可复现 = 影响力:30 行代码 + 公开 repo,让 GCN 在一年内被全社区试遍
延伸阅读
- 论文 PDF:arXiv:1609.02907(9 页正文,附录有完整推导)
- Kipf 自己写的博客:How powerful are Graph Convolutional Networks?(图示比论文清楚)
- 代码:tkipf/gcn (TensorFlow) / tkipf/pygcn (PyTorch)
- 后续:GraphSAGE (NeurIPS 2017) / GAT (ICLR 2018) / GIN (ICLR 2019)
- 综述:Wu et al. “A Comprehensive Survey on Graph Neural Networks” (TNNLS 2020)
关联
- attention —— GAT 用 attention 替换 GCN 的固定邻居权重
- graphrag —— LLM 时代把”先建图再传播”的思想用到检索增强
- pytorch —— PyTorch Geometric / DGL 是 GCN 类模型的主流实现框架
- adam-2014 —— GCN 训练用的优化器,原论文也用 Adam