常见图神经网络模型:GCN、GAT、GraphSAGE
我们做 ADMET 预测时,分子的拓扑结构是核心信息。怎么把这种结构塞进神经网络?图神经网络(GNN)就是答案。GCN、GAT、GraphSAGE 这三个模型,基本覆盖了八成以上的实用场景。
我个人习惯把 GNN 理解成「消息传递」框架。每个原子就是节点,化学键就是边。节点不断从邻居那收集信息,更新自己的特征。说起来简单,但不同的模型在「怎么聚合邻居信息」上各有各的招。下面我按自己的实践经验,一个一个拆开讲。
4.1 GCN:最经典的“平均池化”
GCN(图卷积网络)是最早被广泛使用的 GNN 模型。它的核心操作就是:把邻居节点的特征取个加权平均,然后跟自身特征合并,再做个非线性变换。
这里有个关键的细节:邻接矩阵的归一化。如果不做归一化,度大的节点(也就是相连原子多的)特征会变得特别大,训练很容易崩。GCN 用了对称归一化的拉普拉斯矩阵,保证节点特征在传播时数值稳定。
在 ADMET 里,我一般把 GCN 当作基线模型。原因是它速度快、参数少,对于小分子数据集(比如几百到几千个分子)基本够用。
如果你刚接触图神经网络,先跑一个 GCN 热身。我用它预测过水溶性(logS),两层 GCN + 全局池化,效果就已经超过传统指纹方法了。
下面是 PyTorch Geometric (PyG) 的一个简单 GCN 层示例:
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
class GCNModel(torch.nn.Module):
def __init__(self, in_channels, hidden_channels, out_channels):
super().__init__()
self.conv1 = GCNConv(in_channels, hidden_channels)
self.conv2 = GCNConv(hidden_channels, out_channels)
def forward(self, x, edge_index):
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)
x = self.conv2(x, edge_index)
return x
4.2 GAT:学出来的“加权”
GCN 的聚合权重是固定的(根据度计算),但 GAT(图注意力网络)让模型自己去学每个邻居的重要性。这就是注意力机制。
每个节点对邻居的关注度不一样。比如在分子里,某个官能团的原子可能对活性起决定性作用,GAT 能自动给这些原子更高的权重。
我记得有一次项目里,用 GAT 预测 Caco-2 细胞渗透性,它比 GCN 高了 2-3 个百分点的 AUC。为什么?因为渗透性主要取决于分子表面的极性和氢键位点,GAT 学会把注意力集中在这些关键原子上。
我曾经在一个 5 万分子的数据集上训练 GAT,发现 loss 死活不降。查了半天,原来是学习率设得太高,注意力权重在 0 和 1 之间来回震荡。后来把学习率从 0.01 降到 0.001,训练就稳了。
GAT 代码也非常简洁。PyG 里用 GATConv 替换 GCNConv 就行:
from torch_geometric.nn import GATConv
class GATModel(torch.nn.Module):
def __init__(self, in_channels, hidden_channels, out_channels, heads=8):
super().__init__()
# 多头注意力:每个头学不同关注模式
self.conv1 = GATConv(in_channels, hidden_channels, heads=heads)
self.conv2 = GATConv(hidden_channels * heads, out_channels, heads=1)
def forward(self, x, edge_index):
x = self.conv1(x, edge_index)
x = F.elu(x)
x = self.conv2(x, edge_index)
return x
4.3 GraphSAGE:能搞定新分子的“归纳”
GCN 和 GAT 都是直推式模型——训练时得知道整个图的结构。但实际中我们经常遇到新分子,它在训练集里没见过。GraphSAGE 专为此设计。它通过采样 + 聚合的方式,对每个节点只采样固定数量的邻居,然后用 Mean、LSTM 或 Pooling 来聚合。
说白了这个模型可以对任意新分子直接做预测,不需要重新训练。这对于高通量 ADMET 筛选非常实用。
我用它做过肝毒性预测,模型规模从 10 万分子扩展到 100 万,只需要重新采样邻居,模型参数完全复用。而 GCN 要重新构建整个邻接矩阵,内存吃不住。
PyG 的 SAGEConv 用法类似:
from torch_geometric.nn import SAGEConv
class GraphSAGEModel(torch.nn.Module):
def __init__(self, in_channels, hidden_channels, out_channels):
super().__init__()
self.conv1 = SAGEConv(in_channels, hidden_channels)
self.conv2 = SAGEConv(hidden_channels, out_channels)
def forward(self, x, edge_index):
x = self.conv1(x, edge_index)
x = F.relu(x)
x = self.conv2(x, edge_index)
return x
4.4 三模型对比
你想想看,真到选模型时,最头疼的就是该用哪个。我根据多年的踩坑经验,整理了一个对比表:
| 模型 | 聚合方式 | 是否可归纳 | 适用场景 | 典型ADMET任务 |
|---|---|---|---|---|
| GCN | 度归一化平均 | 否(直推) | 全图已知的小数据集 | 水溶性、logP |
| GAT | 自学习的注意力权重 | 否(直推) | 需要关注关键原子 | 渗透性、毒性位点 |
| GraphSAGE | 采样后聚合(均值等) | 是(归纳) | 大分子库、增量预测 | 肝毒性、代谢稳定性 |
4.5 选择建议
嗯,这里要注意:没有万能模型。如果你的数据规模小(<5000分子),GCN 就够了。如果想解释哪些原子对活性贡献大,优先 GAT。如果数据量很大或者需要实时预测新分子,GraphSAGE 是首选。
我个人最常用的搭配是:先用 GCN 做快速原型验证,然后用 GAT 做精细化调优,最终部署时切到 GraphSAGE 以支持增量数据。这套流程在很多工业项目中都跑通了。
- GCN:简单、稳定、适合基线
- GAT:自动学习邻居权重,可解释性好
- GraphSAGE:归纳式学习,适合大规模动态图
- 代码层面:PyG 的 Conv 接口统一,换模型只需改一个构造函数
你看这个图就清楚了。GCN 和 GAT 是全局一次性传播,GraphSAGE 是采样局部子图。在 ADMET 项目里,我会根据数据量和推理延迟需求在这三者之间切换。