第 4 章:分子指纹与图神经网络基础
做ADMET预测,说白了就是给分子做“性格测试”。
但你得先能用计算机懂的语言描述这个分子。嗯,这就涉及到特征提取。业界常用的两种方法——分子指纹和图神经网络,各有各的脾气。我个人习惯把指纹比作“快照”,把GNN比作“关系网”。
4.1 分子指纹:老派但管用
分子指纹就是用一个固定长度的位向量,来描述分子的结构信息。我在项目中遇到最多的就是Morgan指纹,也叫圆形指纹。它通过枚举原子周围的环境来产生特征,速度快,效果好。
常用的指纹类型:
| 指纹名称 | 特点 | ADMET适用性 |
|---|---|---|
| MACCS | 166个预定义结构片段 | 骨架识别,但丢失细节 |
| Morgan (ECFP) | 基于原子邻域的圆形指纹 | 分布式表示,应用最广 |
| RDKitFP | 对ECFP做了路径优化 | 更适合小分子 |
| AtomPairs | 记录两原子间的距离和类型 | 拓扑距离敏感 |
Tips:在调参时,建议先试ECFP的半径=2,长度=2048。这个配置在大多数ADMET任务上都能守个不错的底线。
用RDKit生成指纹很简单,一行搞定:
from rdkit import Chem
from rdkit.Chem import AllChem
mol = Chem.MolFromSmiles('CC(C)C(=O)O')
fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)
print(fp.ToBitString()[:64] + '...')
但要注意,指纹是离散的。你想想看,它把一个连续的化学空间硬生生压成2048位二进制。这中间信息损失是必然的。我曾经吃过这个亏——把指纹长度从512调到4096,模型反而过拟合了。说白了,不是越长越好。
注意:指纹的哈希碰撞在长尾分子中尤其常见。如果你的数据集里有大量稀有骨架,别指望指纹能区分它们。
4.2 图神经网络:分子的关系网
图神经网络是这几年火起来的方法。它把原子当作节点,化学键当作边,然后在图上做消息传递。为什么会这样?因为分子本质上就是个图结构,何必硬压成一维向量?
核心思路很简单:
- 初始化每个原子的特征向量
- 聚合邻居原子的消息
- 更新当前原子的表示
- 重复K步,得到整个图的表示
我常用的GNN框架是PyTorch Geometric。一个基础的GIN(图同构网络)长这样:
import torch
import torch.nn.functional as F
from torch_geometric.nn import GINConv, global_mean_pool
class GINPredictor(torch.nn.Module):
def __init__(self, num_features, hidden_dim=64, num_layers=3):
super().__init__()
self.convs = torch.nn.ModuleList()
for _ in range(num_layers):
mlp = torch.nn.Sequential(
torch.nn.Linear(num_features, hidden_dim),
torch.nn.ReLU(),
torch.nn.Linear(hidden_dim, hidden_dim)
)
self.convs.append(GINConv(mlp))
self.fc = torch.nn.Linear(hidden_dim, 1) # ADMET预测通常是回归或二分类
def forward(self, x, edge_index, batch):
for conv in self.convs:
x = conv(x, edge_index)
x = F.relu(x)
x = global_mean_pool(x, batch) # 全局池化
return self.fc(x)
这个模型你想想看,本质上是在学“什么样子的原子排列会导致高毒性或低清除率”。我在一个肝脏毒性预测项目里,用三层GIN比传统指纹的AUC高了接近8个点。
4.3 怎么选?什么场景用什么
没有银弹。这是一个很实际的问题:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 快速筛选数万分子 | ECFP + 随机森林 | 计算快,内存友好 |
| 对骨架新颖性要求高 | GIN/GCN | 能泛化到没见过的新片段 |
| 异构数据集(含蛋白结构) | GNN + 注意力机制 | 能利用药物-靶标结构信息 |
我的经验:如果数据量小于5000个分子,优先用指纹+树模型。GNN在小数据上容易过拟合。
当然,你也可以把指纹和GNN结合起来。我个人喜欢用GNN学特征,再拼接上已知的药化规则(比如Lipinski五规则)。这不是什么高深技术,但实战效果往往比纯深度学习好。
4.4 知识体系总览
下面这张SVG图梳理了这一章的核心。从分子输入到任务输出,指纹和GNN分属两条路线,各有各的适用阶段。
4.5 避坑与调参建议
实战中你可能会遇到这些坑:
- 指纹维数灾难:我曾经把位长开到8192,模型直接崩了。嗯,内存扛不住,训练也慢。建议从1024开始逐步往上调。
- GNN过平滑:层数超过4层,所有节点的表示趋于一致。你想想看,这还学个什么?ADMET数据通常2~3层就够。
- 消息传递并行化:分子大小不一。记得用
torch_geometric.data.DataLoader的follow_batch选项,否则GPU利用率上不去。
关键参数速查:
- ECFP半径:2(小分子)或3(含大环结构)
- GNN隐藏维度:64~256
- 学习率:5e-4(AdamW + 余弦退火)
- 批大小:32~128
嗯,这一章就到这里。先把特征工程这一步稳住,后面调参才有的放矢。