化学信息学基础:SMILES、InChI、分子图表示
做分子属性预测,第一件事就是把化学结构变成计算机能懂的语言。你想想看,一个苯环六个碳,在纸上画个六边形就行,但要让机器认出来就得规定一套编码规则。
我刚开始接触这个领域时,也纳闷过:为什么不直接用CAS号?后来踩了坑才明白——CAS号是登记号,跟结构没有直接推导关系。真正的化学信息学三大基础:SMILES、InChI、分子图。这三样东西,你每天都会打交道。
SMILES:最流行的行式表示法
SMILES(Simplified Molecular Input Line Entry System)说白了就是把结构写成一行字符串。这玩意1990年代就有了,到现在还是最常用的。
基本规则其实挺简单:
- 原子用元素符号直接写,比如C、O、N
- 单键直接写,双键用
=,三键用# - 分支用括号
()包裹 - 环结构用数字标记开环位置
- 芳香环用小写字母,比如
c1ccccc1代表苯
举个例子,乙醇的SMILES是CCO。嗯,连字符都省了。再来个复杂点的:对乙酰氨基酚(扑热息痛):
CC(=O)Nc1ccc(cc1)O
这个字符串里,CC(=O)N是酰胺部分,c1ccc(cc1)是苯环,最后的O是羟基。注意看括号里的=O,表示一个双键氧连在碳上。
我在项目中遇到过一个大坑:SMILES不唯一!同一个分子,不同人写出来可能不一样。比如丙酮可以是CC(=O)C,但有人写成C(=O)(C)C,也是对的。这就麻烦了,做数据合并时明明同一个分子,字符串却不相等。
Chem.MolToSmiles(mol, canonical=True)就行。
SMILES的变种与规范化
现在主流工具都能生成规范化SMILES,但要注意:
- Isomeric SMILES:包含手性、同位素信息,用
@表示手性中心方向 - Kekulé SMILES:把所有芳香键都写成单双键交替,不展示芳香性
- DeepSMILES:针对序列模型做了优化,去掉一些括号陷阱
我个人习惯是:做机器学习时统一用RDKit的规范化SMILES,不去搞花哨的变种。原因很简单——你训练一个模型,输入必须是确定性的,否则自己坑自己。
InChI:权威的国际标识符
如果说SMILES是"民间高手",那InChI就是"官方认证"。InChI(International Chemical Identifier)由IUPAC主导开发,目标是给每个分子一个唯一且可解析的标识符。
你看它的结构就知道这玩意多严谨:
InChI=1S/C8H9NO2/c1-6(10)9-7-2-4-8(11)5-3-7/h2-5,11H,1H3,(H,9,10)
这是对乙酰氨基酚的InChI。拆开看:
1S表示版本和标准标志C8H9NO2是分子式/c1-6(10)...是连接层,描述原子连接关系/h2-5,11H,...是氢原子层,规定哪些位置有氢
InChI还有一个"亲儿子"叫InChIKey,是个固定长度的哈希值,方便数据库索引。比如上面那个分子的InChIKey是:
RZVAJINKPMORJF-UHFFFAOYSA-N
注意最后三位-N表示非标准(Non-standard),如果加了立体化学信息就会变成-S。
实际项目中,我常用这个组合:
| 用途 | 推荐编码 | 原因 |
|---|---|---|
| 数据存储、去重 | InChI / InChIKey | 唯一、可逆、标准化 |
| 机器学习输入 | SMILES / 分子图 | 长度短、易解析、可特征化 |
| 展示与交互 | SMILES | 人类可读性好 |
| 论文引用 | InChI | 国际标准、不可歧义 |
分子图表示:计算机眼中的分子
现在我们把分子看作一个图。原子是节点,化学键是边。你想想看,苯环不就是个六元环图吗?甲基不就是个碳连三个氢吗?
分子图通常包含两部分:
- 节点特征:原子类型、杂化方式、形式电荷、是否为芳香原子、氢原子数等
- 边特征:键类型(单/双/三/芳香)、键长、是否在环中、立体化学等
举个例子,用RDKit把SMILES转成分子图特征:
from rdkit import Chem
from rdkit.Chem import AllChem
mol = Chem.MolFromSmiles('CCO')
# 获取原子特征
for atom in mol.GetAtoms():
print(atom.GetAtomicNum(), # 原子序数
atom.GetHybridization(), # 杂化方式
atom.GetFormalCharge(), # 形式电荷
atom.GetIsAromatic()) # 是否芳香
# 获取键特征
for bond in mol.GetBonds():
print(bond.GetBeginAtomIdx(), bond.GetEndAtomIdx(),
bond.GetBondType()) # 键类型
这段代码输出:
6 SP3 0 False
6 SP3 0 False
8 SP3 0 False
0 1 SINGLE
1 2 SINGLE
两个碳原子(原子序数6)和一个氧原子(原子序数8),都是sp3杂化,没有电荷,不做芳香。两个单键连接。
做分子属性预测时,图神经网络(GNN)就是吃这个格式的数据。我早期用手工特征做回归,效果一直上不去;后来换成GNN,直接从分子图学特征,曲线直接起飞。说白了,图才是分子的"原生语言"。
常见分子图表示库对比
现在有几个主流的图表示库,我列一下:
| 库/工具 | 图构建方式 | 优点 | 缺点 |
|---|---|---|---|
| RDKit | 基于Mol对象 | 生态完整、文档多 | 自定义特征需要手写 |
| DGL-LifeSci | 基于DGL图框架 | 与PyTorch无缝集成 | 学习曲线陡 |
| PyTorch Geometric | 自定义Data对象 | 灵活、社区活跃 | 需要手写数据加载 |
| OpenBabel | 文件格式转换 | 支持多种格式 | 图功能较弱 |
三种表示的关系
最后一张图帮你理清楚这三者怎么互相转换:
从左到右,SMILES是人的语言,InChI是数据库的语言,分子图是机器的语言。三者各司其职,又相互贯通。我个人觉得,做项目时优先掌握SMILES和分子图就够用了,InChI更多是在数据清洗和发布时用到。
Chem.MolFromSmiles()和Chem.MolToInchi()就能完成SMILES到InChI的转换。反过来用Chem.MolFromInchi()。转换复杂分子时注意立体化学可能丢失,加sanitize=True参数能避免一些问题。