3. 化学信息学基础:分子表示方法
做ADMET预测,第一步永远是:怎么把分子喂给模型?
说白了,计算机不认识化学结构。它只认数字、向量、矩阵。所以我们必须把分子「翻译」成它能懂的语言。这就是分子表示方法的任务。
我个人习惯把这块叫“模型的入口”。入口要是歪了,后面再怎么调参也白搭。今天我们就捋一遍四种最常用的表示:SMILES、InChI、分子指纹、图表示。
3.1 SMILES——最通用的“分子字符串”
SMILES全称是Simplified Molecular Input Line Entry System。它用一串ASCII字符描述分子结构。你想想看,一个苯环就写成c1ccccc1,多简单。
核心规则:
- 原子用元素符号表示,有机元素默认隐去氢。
- 单键、双键、三键分别用
-=#表示。 - 分支用圆括号,环用数字标记。
- 手性用
@和@@。
举个例子,阿司匹林:
CC(=O)Oc1ccccc1C(=O)O
嗯,这里要注意:SMILES不是唯一的。同一个分子可以写出不同写法。所以我建议在项目中一定要做标准化——用RDKit的 CanonSmiles 或者 MolToSmiles 带参数 isomericSmiles=True。我曾经因为没做标准化,导致两个相同的分子被模型当成不同样本,训练直接崩了。
allHsExplicit=True 可以显式写出氢原子,对某些ADMET模型(比如pKa预测)很关键。
3.2 InChI——更规范的“身份证”
InChI(International Chemical Identifier)是IUPAC推出的标准。它的好处是:给定分子结构,InChI字符串是唯一的(不考虑层可选部分)。
格式长这样:
InChI=1S/C9H8O4/c1-6(10)13-8-5-3-2-4-7(8)9(11)12/h2-5H,1H3,(H,11,12)
这是阿司匹林的InChI。前面是版本号,后面是化学式、连接层、氢层等。
对比SMILES:
| 特性 | SMILES | InChI |
|---|---|---|
| 可读性 | 高,人能大概看懂 | 低,基本是给机器看的 |
| 唯一性 | 不保证 | 保证(主版本) |
| 标准性 | 多种方言(Daylight、OpenSMILES) | IUPAC标准 |
| 长度 | 短 | 长,包含更多信息 |
我在实际项目中,会同时存两种:SMILES用于日常操作和可视化,InChI用于数据库的唯一键。避免因为SMILES写法不同造成的重复。
3.3 分子指纹——把分子变成固定长度的向量
模型真正吃的是数字向量。分子指纹就是干这个的——把结构转换成固定长度的bit位串或者计数向量。
常见类型:
- MACCS密钥: 166个预定义结构片段,位表示有无。
- Morgan指纹(ECFP): 基于摩根算法,从每个原子出发扩展环境,最终哈希成固定长度。最常用的版本是ECFP4(直径4)。
- RDKit拓扑指纹: 类似Morgan,但使用路径枚举。
- AtomPair指纹: 记录原子对的距离和类型。
生成一个ECFP4指纹的代码(Python + RDKit):
from rdkit import Chem
from rdkit.Chem import AllChem
mol = Chem.MolFromSmiles('CC(=O)Oc1ccccc1C(=O)O')
fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)
print(fp.ToBitString()[:80]) # 前80位
你想想看,一个分子变成了2048个0/1。模型就能直接用了。
避坑指南: 我曾经吃过“指纹长度”的亏。用128位Morgan指纹做ADMET分类,AUC一直上不去。后来换成1024位,效果提升明显。但2560位又过拟合了。经验值是:中小数据集512~1024,大数据集1024~2048。
另外,指纹之间的相似度常用Tanimoto系数。这个系数对稀疏位串表现不错,但如果你的分子很大、指纹很密,可以考虑Dice系数。
useFeatures 参数。
3.4 图表示——最接近化学家思维的表示
分子天然就是图:原子是节点,化学键是边。图表示直接把这种结构原封不动地喂给图神经网络(GNN)。
怎么表示成图?
- 节点特征: 原子类型、价电子数、杂化方式、形式电荷、是否在环中等。
- 边特征: 键类型(单/双/三/芳香)、是否共轭、是否在环中等。
- 全局特征: 分子量、LogP、电荷等(很多模型会拼到图读出层)。
举个例子,对于苯环的一个碳原子,节点特征可能是:
原子序数: 6
杂化: SP2
度: 3
形式电荷: 0
在芳香环: 1
氢原子数: 1
这些特征通常用one-hot编码或连续值归一化后拼接成向量。边特征类似。
我在做多任务ADMET预测时,坚持用图表示。原因是:它天然支持多任务共享底层特征,而且能够通过消息传递捕捉长程相互作用(比如一个位点的取代基如何影响远端pKa)。SMILES和指纹都很难做到这一点。
因为不同的ADMET属性往往依赖不同的分子子结构。图神经网络每一层聚合邻居信息,能自动学习不同尺度的化学环境。配合多任务输出头,模型可以共享底层图卷积参数,只在顶层分支特化。这样小样本任务也能从大任务中学到通用表示。
3.5 四种表示方法对比
| 方法 | 输入形式 | 优点 | 缺点 |
|---|---|---|---|
| SMILES | 字符串 | 简洁、可读、工具链成熟 | 非唯一、需标准化、无法直接用于GNN |
| InChI | 字符串 | 唯一、标准化、带化学信息 | 太长、可读性差、解析效率低 |
| 分子指纹 | 固定长度向量 | 适合传统ML、计算快、可解释(部分) | 信息损失、无法捕捉精细结构 |
| 图表示 | 邻接矩阵+特征矩阵 | 保留完整结构、适合GNN、支持多任务 | 需要GNN、计算成本高、图生成有开销 |
3.6 知识结构总览
下面这张图梳理了从分子原始结构到模型输入的整个流程。记住:不同的下游任务,适合的表示方法也不同。
3.7 实际项目中的选型建议
- 做高通量虚拟筛选: 用SMILES + 分子指纹。速度快,baseline好出。
- 做多任务深度学习: 直接上图表示(比如DGL或PyTorch Geometric),配合RDKit做特征工程。
- 做数据库清洗与去重: SMILES做标准化 + InChI做唯一键。我常用
Chem.MolToInchi(mol)来生成。 - 做可解释性分析: 分子指纹的位可以映射回子结构(比如MACCS键),或者用GNN的注意力权重可视化。
嗯,这一章就到这儿。记住:表示方式决定了模型的上限。多花点时间在分子理解上,后面会省很多调试的苦力活。