GraphSAGE 的价值不只是换一种卷积层。它把根据节点特征及邻域生成表示的规则学出来,并结合采样支持大图训练。GraphSAGE 原论文

不要把模型名称当作数据划分

“归纳式”描述模型对训练时未见节点或图的评估设定,不是 GraphSAGE 独占的开关。只要使用可共享的特征变换,其他消息传递模型也可能用于新图;相反,把测试标签、未来边或全量统计量泄露到训练中,换成 GraphSAGE 也不会变成干净实验。

GAT 原论文明确包含归纳式任务。因此,“GCN/GAT 一概不能处理新节点,新增节点必须重训”不是合适的通用结论。GAT 原论文 实现中还需检查缓存:依赖旧图的缓存不能直接复用到变化的图上。

采样器和聚合层分开理解

SAGEConv 定义如何聚合已给定的邻域,NeighborLoader 决定本批次取哪些节点和边。只创建前者不会自动完成邻居采样。PyG 的默认均值式 SAGEConv 对自身和邻域使用不同变换;输出 L2 归一化是可选项,不是所有实现都默认启用。SAGEConv 文档

采样的上下文节点不一定都有本轮监督标签。按 PyG 的邻居采样约定,种子节点位于批次前部,损失和指标应只针对对应种子计算;不能把整批邻居标签顺手全部用于训练。邻居采样教程

一个不依赖图学习框架的检查

下面只验证均值聚合的顺序不变性,以及“本批节点”和“本批监督节点”的区别。它不实现 GraphSAGE 训练。

import numpy as np

neighbors = np.array([[1., 3.], [5., 7.], [3., 2.]])
np.testing.assert_allclose(neighbors.mean(axis=0), neighbors[[2, 0, 1]].mean(axis=0))

node_ids = np.array([10, 20, 30, 40])
seed_count = 2
labels = np.array([0, 1, -1, -1])
seed_labels = labels[:seed_count]
assert (seed_labels >= 0).all()
assert node_ids[:seed_count].tolist() == [10, 20]
assert len(seed_labels) < len(node_ids)
print("aggregation order and supervision boundary checks passed")

有限采样会增加估计波动。记录采样层数、每跳邻居数、是否放回、随机种子和评估采样策略,才能解释两次结果为什么不同。采样层数还要与消息传递层数及边方向相匹配。

我的实验验收顺序

  1. 先说明新节点、新图或未来时间段究竟怎样留出。
  2. 再核对训练可见的特征、边和统计量。
  3. 检查种子损失与上下文节点的边界。
  4. 固定采样与评估协议,比较相同预算下的模型。

来源与核验边界

本篇基于疏锦行图神经网络专题《GraphSAGE与大图训练》讲义,重组采样与归纳学习的关系,并修正过于绝对的模型对比。独立的 NumPy 检查已运行;没有复现 Reddit、PPI 或百万节点训练。视频口头补充尚未逐节核验,原课件不公开。