1. 图神经网络概述与应用领域
1.1 从一张图说起
我第一次接触图神经网络(GNN)是在做药物分子QSAR建模的时候。传统方法把分子描述符排成一维向量,丢进随机森林或XGBoost里跑。效果还行,但总感觉哪里不对劲——分子的空间结构、原子之间的连接关系,全被压没了。你想想看,两个分子功能基团一样、拓扑结构不同,活性可能差十倍,向量化以后却长得差不多。这合理吗?
嗯,图神经网络就是要解决这个问题的。它把数据当成图来处理,每个节点带自己的特征,边描述节点之间的关系。说白了,就是让模型学会“看结构”,而不是只盯着一堆数字。
1.2 图神经网络长什么样?
一个典型的GNN层做三件事:
- 消息传递:每个节点收集邻居的信息,带上边上的属性。
- 聚合:把邻居信息汇总,比如求和、取平均或者用注意力加权。
- 更新:把聚合后的信息和节点自身特征结合起来,更新节点表示。
重复这几步,经过多层GNN,每个节点就能“看到”整个图的结构信息。然后再做个图级别的读出(readout),把节点表示聚合成整个图的向量,拿去做分类或回归。
核心洞察:GNN的本质是让模型自己学会图上的特征工程。以前我们手撸的分子指纹、拓扑指数,现在让网络在训练中自动找出最有效的结构模式。
1.3 GNN在QSAR靶点发现中的位置
传统QSAR流程一般是:收集分子数据 → 计算描述符 → 训练模型 → 预测活性。这里有两个痛点:描述符设计依赖专家经验,而且无法捕捉高阶结构关系;模型泛化到新骨架分子时经常翻车。
GNN直接操作分子图(原子是节点,化学键是边),天然保留了分子拓扑。我在一个激酶靶点项目里遇到过:用传统方法做虚拟筛选,排名靠前的分子在另一系列上活性全丢了;换成GNN后,同一个模型在不同骨架上都抓到了关键药效团。当然,这不是说GNN万能,它数据需求量更大,调参也更麻烦。
| 维度 | 传统QSAR | GNN-based QSAR |
|---|---|---|
| 输入形式 | 固定长度特征向量 | 图结构 + 节点/边属性 |
| 特征工程 | 人工设计描述符 | 自动学习结构表示 |
| 泛化能力 | 弱(对碎片依赖强) | 相对强(捕捉拓扑模式) |
| 计算成本 | 低(传统ML) | 中高(需要GPU加速) |
| 可解释性 | 中等(SHAP等) | 中等(注意力/梯度解释) |
我的建议:如果项目数据量少于几百个分子,传统方法往往更稳。GNN的优势在数据量上千、分子结构多样性高时才会明显体现。别一上来就堆GNN,先跑个基线。
1.4 GNN在药物发现中的典型应用
这几年我陆续参与了几个靶点发现项目,GNN的应用主要集中在这几个方向:
- 分子性质预测:溶解度、毒性、ADMET等。GNN在这个场景下精度超过大多数指纹基模型。
- 药物-靶标相互作用预测:把药物和靶标分别建模成图,用双塔GNN预测结合亲和力。我在一个GPCR项目里试过,Top-1% 命中率比对接评分高出一截。
- de novo 分子生成:用图生成模型(如GraphVAE、MolGAN)在化学空间里搜索新分子,再通过GNN打分筛选。
- 蛋白质结构预测与对接:AlphaFold 用的其实是图注意力机制,后面很多增强方法也用GNN做残基接触图。
- 定量构效关系(QSAR):直接预测IC50、pIC50等连续值,GNN已经成了主流方法。
避坑指南:我曾经在一个数据集里发现,GNN模型在测试集上精度很高,但换一批分子直接崩了。后来排查是数据泄漏——分子图里不小心包含了“活性片段”的全局特征。记住,图数据预处理时必须按分子严格切分,不能混入任何测试集信息。
1.5 完整流程框架
下面这张图概括了从分子图到靶点预测的核心流程:
1.6 实用工具与第一步
简单说下跑起GNN需要的环境。我个人习惯用PyTorch Geometric(PyG),它把消息传递层都封装好了。安装命令如下:
pip install torch torchvision torchaudio
pip install torch-scatter torch-sparse torch-cluster torch-spline-conv
pip install torch-geometric
你拿到一个分子数据集后,可以先转换成图格式。下面是个快速示例,用RDKit把分子转成PyG的Data对象:
from rdkit import Chem
from torch_geometric.data import Data
import torch
def mol_to_graph(smiles):
mol = Chem.MolFromSmiles(smiles)
# 简化示例:只取原子序数和键类型
atoms = [atom.GetAtomicNum() for atom in mol.GetAtoms()]
edges = [[bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()] for bond in mol.GetBonds()]
x = torch.tensor(atoms, dtype=torch.long).view(-1, 1)
edge_index = torch.tensor(edges, dtype=torch.long).t().contiguous()
return Data(x=x, edge_index=edge_index)
这样,一个分子就变成了图数据。下一步可以喂给GNN模型训练了。
实用提示:一开始跑小分子集时,重点关注图是否“连得通”。我曾经遇到一个分子没有键(孤立的单个原子),图数据里就一个节点,GNN直接报错。加个节点数检查能省很多时间。
1.7 小结:为什么GNN值得学?
我在给团队做技术分享时经常说:图神经网络不是魔法,但它确实打开了一扇新的门。在QSAR靶点发现这个领域,它能帮你绕过手工特征工程,直接跟分子结构对话。当然,代价是你要学会处理图数据、调通GPU、忍受更长的训练时间。但看看这两年顶会论文——Graph Isomorphism Networks、注意力机制、等变GNN……图上的深度学习正在快速进化,不跟上来就真的落后了。
掌握了GNN,你不仅能做更好的活性预测,还能拓展到蛋白质相互作用、代谢通路分析,甚至结合表达数据做多模态建模。嗯,这些都是后面章节要讲的内容。