4、GraphSAGE:采样与聚合、归纳式学习、大规模图上的应用
说实话,GCN 虽然好用,但它有个硬伤——它是直推式的。什么意思呢?就是训练的时候,你得把整张图都端上来,所有节点都得在场。一旦来了新节点,不好意思,得重新训练。这在工业界太不现实了。
我当年在金融风控项目里就踩过这个坑。每天都有新用户注册,新交易产生,图结构一直在变。用 GCN 的话,每天凌晨都得全量重训,算力扛不住,时效性也差。后来换成了 GraphSAGE,问题就解决了。
GraphSAGE 的核心思想其实很简单:我不学节点的 embedding,我学怎么聚合邻居信息。这样新节点来了,我只要拿它的邻居特征,走一遍聚合函数,就能算出它的 embedding。这就是归纳式学习。
4.1 采样:邻居不是越多越好
GCN 做消息传递时,用的是全邻居。GraphSAGE 不一样,它采样。为什么?
- 全邻居的计算复杂度是 O(|V|×|E|),图大了根本扛不住
- 每个节点的度差异很大,有的节点几万个邻居,有的就两三个
- 采样能控制计算量,让训练更稳定
GraphSAGE 的采样策略是固定大小的邻居采样。比如设定采样数 K=3,那就从邻居里随机抽 3 个。如果邻居不够 3 个,就重复采样补齐。
核心公式:第 l 层的邻居采样数 Sl,通常 S1 > S2 > S3,越往外层采得越少。
我个人习惯设 S1=25, S2=10。为什么这么设?因为第一层离目标节点近,信息最相关,多采点;第二层是间接邻居,信息量递减,少采点。这样既保留了局部结构,又控制了计算量。
避坑指南:我曾经把采样数设得太大,结果每个 batch 的邻居数爆炸,显存直接 OOM。后来改成逐层递减采样,问题就解决了。你想想看,如果每层都采 25 个,两层就是 25×25=625 个节点,三层就是 15625 个。这谁顶得住?
4.2 聚合:三种方式各有千秋
采样完邻居,下一步就是聚合。GraphSAGE 提供了三种聚合函数:
| 聚合方式 | 特点 | 适用场景 |
|---|---|---|
| Mean 聚合 | 对邻居特征取平均,简单高效 | 节点度比较均匀的场景 |
| LSTM 聚合 | 对邻居序列建模,表达能力更强 | 邻居有顺序关系的场景 |
| Pooling 聚合 | 对每个邻居做 MLP,再取 max/mean | 需要提取最显著特征的场景 |
我在金融风控里用得最多的是 Mean 聚合。为什么?因为简单、稳定、不容易过拟合。LSTM 虽然理论上更强,但邻居的顺序在金融图里其实没什么意义——难道说张三的邻居按 ID 排序就有信息量?不存在的。
聚合的数学表达是这样的:
h_v^(k) = σ( W · MEAN( { h_v^(k-1) } ∪ { h_u^(k-1), ∀u ∈ N(v) } ) )
说白了,就是把目标节点自己的特征,和采样到的邻居特征,一起取平均,再过一个线性层加激活函数。嗯,就这么简单。
4.3 归纳式学习:这才是 GraphSAGE 的精髓
GCN 学的是每个节点的 embedding,GraphSAGE 学的是聚合函数。这个区别太关键了。
举个例子。假设你训练好了 GraphSAGE 模型,用来做反欺诈。第二天来了个新用户,他的交易记录、设备信息、IP 地址都有。在 GCN 里,你得把新用户加到图上,重新跑一遍前向传播,甚至可能得重新训练。但在 GraphSAGE 里,你只需要:
- 找到新用户的 K 个邻居
- 把邻居特征喂给聚合函数
- 输出新用户的 embedding
整个过程不需要重新训练,这就是归纳式学习的威力。
关键区别:直推式学习(GCN)—— 训练时所有节点可见,新节点需要重训。归纳式学习(GraphSAGE)—— 训练时只学聚合函数,新节点直接推理。
我记得有一次线上部署,模型已经跑了三个月,突然要接入一个新的数据源。用 GraphSAGE 的话,我只需要把新数据源的特征映射到已有的特征空间,然后走一遍聚合流程就行。整个上线过程不到一小时。要是用 GCN,光重训就得花半天。
4.4 大规模图上的应用:Mini-Batch 训练
GraphSAGE 能上大规模图,核心原因就是它支持 Mini-Batch 训练。GCN 是全图训练,一次要把整张图加载到显存里。GraphSAGE 每次只处理一个 Batch 的节点和它们的采样邻居。
训练流程是这样的:
- 从图中随机采样一个 Batch 的目标节点
- 对每个目标节点,采样 K 层邻居
- 构建子图,只包含这些节点和边
- 在这个子图上做前向传播和反向传播
这样做的好处很明显:
- 显存占用可控,只跟 Batch Size 和采样数有关
- 可以并行训练,每个 Batch 独立计算
- 支持流式数据,新数据来了直接处理
注意:Batch Size 不是越大越好。我试过把 Batch Size 从 256 提到 1024,训练速度没快多少,显存倒是翻了三倍。后来发现 512 是个不错的平衡点。具体多少合适,得看你的图密度和显存大小。
4.5 金融风控实战:反欺诈场景
最后分享一个我在反欺诈项目里的实际配置。这个场景是检测团伙欺诈,图里有用户节点、设备节点、IP 节点,边表示关联关系。
模型配置:
# GraphSAGE 参数配置
num_layers = 2 # 两层聚合
sample_sizes = [25, 10] # 第一层采25个,第二层采10个
hidden_dim = 128 # 隐藏层维度
aggregator = 'mean' # 均值聚合
batch_size = 512 # 每批处理512个节点
learning_rate = 0.001 # 学习率
dropout = 0.3 # 防止过拟合
效果怎么样?相比之前的 GCN 方案:
- 训练时间从 6 小时降到 40 分钟
- 新用户上线延迟从 1 天降到 实时
- AUC 从 0.89 提升到 0.92
说实话,提升最大的不是 AUC,而是工程上的可落地性。以前每次模型更新都要协调多个团队,现在一个人就能搞定。这才是 GraphSAGE 在工业界真正受欢迎的原因。
我的建议:如果你刚开始用 GraphSAGE,先从 Mean 聚合 + 两层采样开始。这个配置最稳,也最容易调参。等跑通了,再尝试 Pooling 或者 LSTM。别一上来就整花活,容易翻车。
好了,GraphSAGE 的核心内容就这些。采样控制计算量,聚合提取邻居信息,归纳式学习让模型能处理新节点,Mini-Batch 让大规模训练成为可能。这四个点串起来,就是 GraphSAGE 能在工业界大规模落地的原因。