经典图模型与节点分类实践#
学习目标与记号#
比较 GCN、GAT、GraphSAGE 和 GIN 的聚合规则、表达能力与计算代价;
解释邻居采样、归纳学习、图级读出及同质性假设的适用边界;
建立完整的节点分类实验流程,包括划分数据、设置不使用图结构的对照模型、评价模型、每次只改变一个模型组件进行比较,以及报告计算时间和内存;
本节沿用统一记号:普通小写字母表示标量,粗体小写字母表示向量,粗体大写字母表示矩阵或高阶张量;层编号写作上标 \([l]\),节点、样本或边编号写作下标;转置写作 \(\trans\)。除非另有说明,节点特征按行存放,邻接约定为 \(A_{ij}>0\) 表示节点 \(j\) 向节点 \(i\) 发送消息。正文与练习中的程序都应同时检查数值结果和数组维度。本节练习的参考答案见 经典图模型与节点分类实践答案。
比较 GraphSAGE 与 GIN 时,应以 消息传递框架 和 聚合器的信息保留能力 为共同基线,并与 GCN、GAT 在相同数据划分下比较。
GCN 和 GAT 并不是图神经网络的全部。GraphSAGE 面向大图与未见节点的归纳推断,GIN 强调对不同邻域多重集合的区分能力。模型选择不应只按发表时间或排行榜,而要同时考虑图是否动态、是否需要采样、结构同质性、任务层级和计算预算。
GraphSAGE#
GraphSAGE 1Hamilton、Ying 与 Leskovec(2017),Inductive Representation Learning on Large Graphs。 在每层为节点采样固定数量的邻居,先聚合邻居,再与节点自身表示组合。均值版本可写为
其中 \(\mathcal{S}_l(v)\) 是本层采样邻居;若输入与聚合表示均为 \(d^{[l-1]}\) 维,则 \(\bW^{[l]}\in\mathbb{R}^{2d^{[l-1]}\times d^{[l]}}\)。参数由特征聚合规则定义,而不是为每个节点保存独立嵌入,因此可以应用到训练时未见、但具有特征和邻域的新节点。采样控制计算量,却会引入随机方差;高阶邻居采样数还会按各层扇出相乘增长。
GIN#
图同构网络(graph isomorphism network,GIN) 2Xu 等(2019),How Powerful are Graph Neural Networks? 使用求和聚合与 MLP:
求和保留邻居多重性;在适当条件下,足够表达力的 MLP 可以把不同的有限多重集合映射到不同表示,使 GIN 的区分能力与一维 Weisfeiler–Lehman 检验紧密相关。这不是“能区分所有非同构图”的保证:一维 WL 本身存在无法区分的图,有限宽度、优化和数据还会进一步限制实际模型。
模型比较#
图 39 四类经典模型都在聚合邻域,但边权、采样、更新函数和主要用途不同#
模型 |
邻域权重或聚合 |
典型优势 |
主要限制 |
|---|---|---|---|
GCN |
固定度归一化加权和 |
简洁、高效基线 |
权重不随特征变化,深层易平滑 |
GAT |
学习的邻域注意力 |
邻居贡献可自适应 |
多头边得分增加内存与时间 |
GraphSAGE |
采样后 mean/max/LSTM 聚合 |
归纳推断与大图训练 |
采样方差和邻域爆炸 |
GIN |
求和加 MLP |
较强的结构区分能力 |
求和尺度随度数变化 |
同质性与任务适配#
许多基础 GNN 隐含局部平滑假设:相连节点倾向具有相似标签或有用特征。异质性较强时,简单聚合可能混合来自不同类别的信号。此时可使用关系类型、符号边、可学习兼容性、跳层或结构编码,也应始终保留只用节点特征的 MLP 基线,以判断结构究竟提供帮助还是噪声。
节点分类实验流程#
验证节点、边、特征、标签和掩码对齐,记录孤立节点与类别比例;
根据传导或归纳目标建立训练、验证、测试划分,阻止未来边和测试边泄漏;
建立多数类、逻辑回归或 MLP 基线,再训练 GCN、GAT 等模型;
只用验证集选择深度、宽度、学习率、正则化和早停轮次;
冻结方案后,在测试集报告多种子均值与标准差,同时报告参数量、时间和峰值内存。
类别较均衡时可报告准确率;不均衡时还应报告 macro-F1、每类召回率或与任务代价一致的指标。节点分类中的节点并非独立样本,普通独立同分布置信区间可能不适用;至少应通过多个训练随机种子和合理的数据划分表达不确定性。
划分检查代码#
下面的函数检查节点分类中的三组节点划分是否满足最基本的格式要求。train_mask、valid_mask 和 test_mask 都应是长度等于节点数的一维真假标记数组;第 \(i\) 个位置为 True,表示节点 \(i\) 属于相应的数据集。检查通过后,函数返回转换为布尔类型的三个数组,后续可以分别用它们选出训练节点、验证节点和测试节点。
import numpy as np
def validate_masks(train_mask, valid_mask, test_mask):
masks = [np.asarray(x, dtype=bool) for x in (train_mask, valid_mask, test_mask)]
if len({x.shape for x in masks}) != 1 or masks[0].ndim != 1:
raise ValueError("三个掩码必须是同形一维数组")
overlap = (masks[0] & masks[1]) | (masks[0] & masks[2]) | (masks[1] & masks[2])
if overlap.any():
raise ValueError("训练、验证和测试掩码必须互斥")
if any(not x.any() for x in masks):
raise ValueError("每个划分至少包含一个节点")
return masks
代码首先把三个输入转换为布尔数组,然后检查它们是否都是大小相同的一维数组。按位“与”运算用于找出同时出现在两组数据中的节点;一旦发现重叠,函数就会报告错误。代码还要求每一组至少包含一个节点。全部检查通过后,函数返回三个掩码。它没有要求所有节点都必须属于其中一组,因此图中可以保留尚未标注或暂不参与评价的节点。
检查范围
这个函数只能检查三组节点是否重叠以及数组格式是否正确,不能发现测试边、未来关系或使用全部数据计算的预处理数值是否提前进入了训练过程。遇到这些任务时,还需要另外检查训练阶段使用的节点、边、时间信息和数据处理步骤是否符合既定的数据划分。
核心推导与实现核验#
核心关系
推导路径。 GIN 把节点自身状态与邻居求和分开保留,再用共享 MLP 进行非线性映射;GraphSAGE 则从邻域采样并把自身与邻居聚合结果拼接,重点解决归纳推断和计算扩张。
关键条件
均值无法区分多重集合 \(\{x\}\) 与 \(\{x,x\}\),因为两者均值相同;求和结果分别为 \(x\) 与 \(2x\),因而能够保留重复次数。GIN 的表达力结论还要求有限特征域和具有足够表达能力的 MLP,不能脱离这些假设。
数据规模
若每个节点的自身表示和邻居汇总结果都含 \(d\) 个数,GraphSAGE 拼接后每个节点共有 \(2d\) 个输入数,因此权重矩阵大小为 \(2d\times d_{\mathrm{out}}\)。GIN 相加的自身表示与邻居表示必须同为 \(d\) 维;图级任务最后还要把数量不同的节点汇总成宽度固定的向量。
常见误区
采样必须只使用部署时可见的邻域;测试边、验证指标或全图预处理统计量不能泄漏。比较模型时要控制参数量、训练预算和数据划分。
动手检查
用重复邻居构造 mean 与 sum 的反例;固定采样种子核对 GraphSAGE;检查训练、验证、测试掩码互斥,并用无边 MLP 基线验证结构增益。
数值稳定性与规模
GIN 求和在高阶节点处尺度较大,可配合归一化与合理初始化;邻居采样要处理空集合并记录随机种子。指标分母为 0 时采用明确约定。
本节小结#
GraphSAGE 通过邻居采样与共享聚合实现大图上的归纳学习。
GIN 用求和和 MLP 增强对邻域多重集合的区分能力,但仍受 WL 上界限制。
为了使模型比较结果可靠,应设置不使用图结构的对照模型,采用不会泄漏信息的数据划分,报告多个随机种子下的结果以及计算时间和内存。
综合练习#
程序题应固定随机种子、写出维度断言并报告运行环境。全部参考答案见 经典图模型与节点分类实践答案。
GraphSAGE 单步计算。 节点 \(v\) 的标量自身表示为 2,三个邻居表示为 \(1,3,5\)。先计算 mean 聚合,再把自身与聚合结果拼成行向量,并使用 \(\bW=\begin{bmatrix}1&-1\\0.5&0.5\end{bmatrix}\) 和 ReLU 计算更新后的二维表示。
多重集合区分证明。 证明 mean 聚合不能区分 \(\{\bx\}\) 与 \(\{\bx,\bx\}\),而 sum 在 \(\bx\ne\bzero\) 时可以区分。进一步说明这为什么支持 GIN 使用 sum,但仍不足以证明有限宽度的 GIN 能区分所有非同构图。
GIN 更新计算。 对标量状态,令中心节点 \(h_v=2\)、邻居状态为 \(1,3,5\)、\(\epsilon=0.5\),且 MLP 暂取恒等映射。计算 GIN 更新前的聚合输入和输出;再分别计算 \(\epsilon=0\) 与 \(\epsilon=-1\) 时的结果并解释自身项的变化。
采样规模计算。 两层 GraphSAGE 对一批 128 个目标节点分别采样 10 个一跳邻居,并为每个一跳邻居采样 5 个二跳邻居。忽略邻居重叠,计算最多涉及的节点出现次数和采样边数;写出一般批量大小 \(m\)、扇出 \(s_1,s_2\) 下的公式,并与全邻居平均度为 \(d\) 的规模比较。
GraphSAGE 采样实现。 实现接受邻接表、目标节点、扇出和随机生成器的无放回邻居采样器,以及一层 mean GraphSAGE。程序应处理度数小于扇出、孤立节点、重复邻居和未见节点;返回实际采样边,以便固定种子复现和计算成本。
GIN 实现与性质核验。 基于
edge_index实现一层 GIN,支持固定或可学习 \(\epsilon\) 和小型 MLP。用第 2、3 题核验 sum 多重性与自身项,再按照 手算结果与可信实现对照 的原则,与逐节点循环或可信库层比较前向和梯度;测试节点置换等变性、高阶节点尺度和空邻域。划分与归纳测试。 实现训练、验证、测试掩码及边集合检查,确保三者互斥,并为归纳设置验证训练阶段没有使用未见节点及其边。构造包含未来边或测试边的错误图,确认检查程序能报告结构泄漏;再验证只要新节点有特征和可见邻域,GraphSAGE 就能执行前向预测。
五种模型的比较。 在同一节点分类数据上比较 MLP、GCN、GAT、GraphSAGE 和 GIN。各模型使用相同的训练集、验证集和测试集划分、随机种子、输入特征、近似参数量和最大训练更新次数,并使用同一个验证集和相同标准选择模型;报告准确率、macro-F1、训练时间、固定节点批量预测时间、峰值内存、参数量、实际处理边数和图层运行次数。
GraphSAGE 扇出比较。 比较若干两层扇出组合,例如 \((5,5)\)、\((10,5)\)、\((15,10)\) 与全邻居。固定数据划分、随机种子集合、模型宽度、训练更新次数、目标节点批量大小和评价代码;报告预测质量、训练时间、固定批量预测时间、峰值内存、采样节点/边数、图层调用次数和多次采样造成的预测波动。
结构、特征与同质性。 比较真实图、随机重连图、去除全部边的 MLP,以及只用度数等结构特征的模型,并在 GCN、GraphSAGE 或 GIN 中至少选择两种模型。固定数据划分、随机种子集合、参数量范围、训练更新次数和评价程序;报告预测质量、训练时间、固定批量预测时间、峰值内存、实际边数和图层调用次数,并计算各图的标签同质性指标。