分子数据基础:SMILES、InChI 与图结构

做 ADMET 预测,第一道坎就是怎么把分子“喂”给模型。

你可能手头有几十万个化合物,每个都是字符串或结构文件。模型看不懂化学式,它只认向量、图或者序列。所以,分子表示就是搭在化学世界和深度学习之间的桥。

我个人习惯先搞清楚三套表示法:SMILES、InChI 和分子图。前两个是文本形式,最后一个是显式拓扑结构。下面一个一个说。


1. SMILES 表示法

SMILES 全称 Simplified Molecular Input Line Entry System。说白了,就是一条字符串,把分子“打平”写出来。

  • 原子:大写字母代表元素,比如 C 是碳,O 是氧。小写字母 c 表示芳香碳。
  • 键:单键默认不写,双键用 =,三键用 #。
  • 分支:用圆括号 () 括起来。比如乙醇:CCO;异丙醇:CC(C)O。
  • 环:用数字标记环的起点和终点,比如苯:c1ccccc1。
小技巧:RDKit 生成 SMILES 默认会尽量“规范化”,同一个分子可能有多种写法。我建议训练前统一用 Chem.MolToSmiles(mol, canonical=True) 转一下,否则模型会学到“写法不同即分子不同”的假规律。

举个例子,阿司匹林(阿斯匹林)的 SMILES:

CC(=O)Oc1ccccc1C(=O)O

看着复杂,拆开其实很简单:一个苯环,连着羧基和酯基。我在做 Tox21 数据清洗时,发现原始数据里有几百个 SMILES 写错了环数字或者漏了括号——跑出来的模型性能直接掉 5 个点。所以,数据预处理时务必用 RDKit 校验。


2. InChI 与国际化学标识符

SMILES 虽然流行,但它不唯一。同一个分子,不同工具、不同规则能写出不同 SMILES。InChI 就是来解决这个问题的。

InChI(International Chemical Identifier)由 IUPAC 制定,是一种分层表示的规范标识符。它包含了分子的连接性、同位素、立体化学和电荷信息。

比如水的 InChI:

InChI=1S/H2O/h1H2

结构是:版本 1S,分子式 H2O,连接层 /h1H2(表示一个氢原子两个氢)。

InChIKey 是哈希后的 27 字符定长串,适合数据库索引。我一般在做跨数据集合并时用 InChIKey 去重,很少用 SMILES——因为不同来源的 SMILES 写法差异太大。

注意:InChI 生成速度比 SMILES 慢很多,一次处理百万级分子时,建议用多进程。我曾经因为单线程跑一个 50 万数据集,等了两个半小时才发现 RDKit 的 MolToInchi 是纯 Python 实现的……后来换成 MolToInchiKey 快了三倍。

3. 分子图结构

图神经网络的兴起让分子图成为主流输入。每个原子是一个节点,每个化学键是一条边。节点特征通常包含:原子种类、度数、电荷、是否在环中、杂化类型等。边特征包含键类型(单/双/三/芳香键)、是否共轭等。

我从 SMILES 构建分子图的典型流程:

  1. 用 RDKit 读取 SMILES,生成 Mol 对象。
  2. 提取原子特征(比如 one-hot 编码元素、隐式氢数、形式电荷)。
  3. 提取键特征(键类型、是否在环中)。
  4. 组装成 torch_geometric.data.Data 或 dgl.DGLGraph。
核心公式:分子图 G = (V, E),其中 V 是原子节点集合,E 是键边集合。每个节点 v ∈ V 有特征向量 x_v,每条边 e ∈ E 有特征向量 w_e。

你不必每次自己写特征提取,rdkit.Chem.rdMolDescriptors 和 dgllife.utils 都有现成函数。但要注意特征对齐:训练集和测试集必须用同一套特征定义。有一次我换了 RDKit 版本,原子特征顺序变了,模型直接崩了。


4. 开源 ADMET 数据集概览

做 ADMET 预测离不开高质量标注数据。下面是我常用的几个公开数据集:

数据集 任务类型 分子数 关键标签 来源
Tox21 多分类(12 个毒性终点) ~7,800 NR-AR, NR-AR-LBD, SR-ARE 等 NIH Tox21 挑战
ESOL 回归(水溶性 logS) 1,128 实验测量的溶解度 Delaney (2004)
FreeSolv 回归(水合自由能) 643 ΔG (kcal/mol) Mobley Lab
Lipophilicity 回归(logD7.4) 4,200 实验 logD ChEMBL 子集
BBBP 二分类(血脑屏障透过性) ~2,000 是否透过 MoleculeNet
选数据原则:小数据集(FreeSolv、ESOL)适合做迁移学习或预训练测试;大数据集(Tox21)适合做多任务训练。我一般把 Tox21 和 BBBP 一起做多任务,效果比单独训练好 1-2% AUC。

下载方式:MoleculeNet 已经整合了大部分数据集,用 deepchem.molnet.load_tox21 或 dgllife.data.Tox21 就能直接拉。不建议自己爬,一是伦理问题,二是数据清洗太耗时。


5. 知识体系图

下面这张 SVG 概括了从分子表示到数据集的完整路径:

分子数据基础 & ADMET 数据集概览 分子表示 SMILES 字符串 InChI / InChIKey 分子图 (GNN) 开源 ADMET 数据集 数据集 --> Tox21 12个毒性终点 ESOL 水溶性 logS FreeSolv 水合自由能 BBBP 血脑屏障透过 自监督预训练加速建模 图:知识体系流程图

6. 实用小工具和日常避坑

  • 快速查看分子:from rdkit.Chem import Draw; Draw.MolToImage(mol) 直接画图。
  • SMILES 统一:训练前跑一遍 Chem.MolFromSmiles(smi) + Chem.MolToSmiles(mol) 做规范化。
  • 数据集拆分:不要用随机拆分,用 scaffold 拆分(基于分子骨架),否则测试集和训练集太像,结果虚高。
  • 内存管理:处理 10 万以上分子时,我建议用 pandas 分批读,每批 5000 个分子转图,不然显存爆掉。
我曾经踩过的坑:用 SMILES 做数据增强(比如随机 SMILES),结果同一分子生成了不同写法,模型学到的是“写法假象”而不是化学性质。后来改成只做原子/键 masking 或者图增强,效果好得多。

好了,这些就是分子数据基础的全部要点。下一步咱们就可以拿着这些数据,开始搭建自监督预训练模型了。