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。我曾经因为没做标准化,导致两个相同的分子被模型当成不同样本,训练直接崩了。

小技巧: 用RDKit生成SMILES时,加上 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:

特性SMILESInChI
可读性高,人能大概看懂低,基本是给机器看的
唯一性不保证保证(主版本)
标准性多种方言(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系数。

注意: 不同版本的RDKit生成的Morgan指纹可能有细微差异(哈希函数不同)。做复现研究时,一定要固定RDKit版本和 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 知识结构总览

下面这张图梳理了从分子原始结构到模型输入的整个流程。记住:不同的下游任务,适合的表示方法也不同。

分子表示方法知识结构 分子结构(原始) SMILES 字符串 InChI 字符串 分子指纹(位向量) 图表示(节点+边) 下游任务:ADMET 属性预测(多任务学习) 选择策略 小样本传统ML → 分子指纹(或SMILES + 描述符) 大样本/多任务 → 图表示 + GNN;数据库存储 → InChI;日常实验 → SMILES

3.7 实际项目中的选型建议

  1. 做高通量虚拟筛选: 用SMILES + 分子指纹。速度快,baseline好出。
  2. 做多任务深度学习: 直接上图表示(比如DGL或PyTorch Geometric),配合RDKit做特征工程。
  3. 做数据库清洗与去重: SMILES做标准化 + InChI做唯一键。我常用 Chem.MolToInchi(mol) 来生成。
  4. 做可解释性分析: 分子指纹的位可以映射回子结构(比如MACCS键),或者用GNN的注意力权重可视化。
我的个人经验: 如果时间紧张,先用Morgan指纹跑一个简单的随机森林,看看数据噪声大不大。数据质量不好时,再高级的GNN也是白搭。等确认数据靠谱了,再上多任务图模型。

嗯,这一章就到这儿。记住:表示方式决定了模型的上限。多花点时间在分子理解上,后面会省很多调试的苦力活。