分子表示方法:SMILES、分子图、分子指纹

做药物设计的,天天跟分子打交道。但你有没有想过——计算机是怎么“看懂”一个分子的?

说白了,机器不能直接理解结构式。它需要一种数学语言来描述分子。我早年做高通量筛选时,就踩过这个坑:把分子结构直接扔进模型,结果模型啥也没学到。后来才明白,分子表示是生成模型的地基。地基没打好,后面全白搭。

这一章,我们就来聊聊三种最常用的分子表示法:SMILES、分子图和分子指纹。这三种各有各的脾气,我们逐个来看。

2.1 你也许不熟悉的“自然语言”——SMILES

SMILES 全称是 Simplified Molecular Input Line Entry System。名字挺长,翻译过来就是“简化分子线性输入规范”。它的核心想法很简单:用一串字符来描述一个分子。

举个例子,乙醇的 SMILES 是 CCO。你看,三个字母,搞定。

规则其实不复杂:

  • 原子用元素符号表示,比如 C(碳)、O(氧)、N(氮)
  • 单键直接写原子符号,双键用 =,三键用 #
  • 分支用括号 () 括起来
  • 环结构用数字标记,比如 C1CCCCC1 代表环己烷

我个人习惯,在写 SMILES 时特别留意芳香性。苯环有两种写法:一种是 c1ccccc1(小写 c 表示芳香碳),另一种是 C1=CC=CC=C1(用双键表示)。在生成模型里,多数处理 SMILES 的模型更吃小写芳香写法,更稳定。

我的小技巧:做 GAN 训练时,尽量统一为标准化 SMILES。用 RDKit 的 Chem.MolToSmiles() 跑一遍,能把同一种分子变成唯一表示。这能避免模型“记住”多种写法,白白浪费计算资源。

SMILES 的优势在于轻量。一个分子就是一行字符串,非常适合文本类生成模型(比如 RNN、Transformer)。但问题也在这里:它是一个顺序表示,而分子本质上是图结构。有时候,两个看似相似的 SMILES 字符串,对应分子可能差别很大。

我举个例子:CC(=O)O 是乙酸,而 CC(=O)O 如果其中一个 C 位置写错,可能就是别的分子了。我曾因为 SMILES 解析问题,导致一批虚拟筛选结果全是废的。嗯,从那以后我就在代码里加了SMILES 校验环。

2.2 更贴近化学直觉的方式:分子图

你想想看,化学家怎么看分子?画结构式,上面是原子,原子之间连着键。这不就是个图吗?

分子图把原子看作节点(Node),化学键看作边(Edge)。节点有特征,比如原子类型、电荷、是否在环里。边也有特征,比如单键、双键、芳香键。

用图来表示分子,好处太多了:

  • 它保留了分子的拓扑结构
  • 它不依赖原子编号顺序
  • 它天然适合图神经网络(GNN)

在 GAN 生成化合物这个任务里,分子图是生成质量最高的表示之一。GNN 直接在图上做操作,可以生成无缝的、化学上合理的新分子。我做过对比:同样的 GAN 架构,用图生成的分子里,合法比例比用 SMILES 高出 20% 以上。

但分子图也有它的“小脾气”:

  • 实现复杂:相比文本,图的数据结构更麻烦
  • 计算开销大:大分子图的邻接矩阵很稀疏
  • 生成需保证连通性:图生成器容易生成多个不连通的碎片

避坑指南:我曾经踩过一个大坑——图生成模型输出了一堆“悬浮”原子,整个分子图是不连通的。后来我在损失函数里加了一个连通性惩罚项,要求生成的图必须包含所有原子。你看,这个细节不做,生成的分子就是一团乱麻。

2.3 不只是“指纹”:分子指纹的本质

分子指纹,名字起得挺形象。像人的指纹一样,它把分子信息压缩成一个固定长度的二进制向量或整数向量。

最常见的指纹类型:

类型 说明 特点
MACCS 键 166 个预定义子结构,有则位为 1 解释性强,但分辨率不高
ECFP (Morgan 指纹) 基于原子环境,可配置半径 信息丰富,是生成模型常客
RDKit 拓扑指纹 路径基,子结构枚举 适合相似度搜索

在 GAN 里,分子指纹的作用很明确:它是判别器(Discriminator)的好帮手。判别器需要判断一个分子是不是“像真药”,而指纹恰好能捕捉那些关键的药效团和子结构模式。

我用 RDKit 计算 ECFP4 指纹的代码大概长这样:

from rdkit import Chem
from rdkit.Chem import AllChem

mol = Chem.MolFromSmiles('CCO')
fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=1024)
print(fp.ToBitString()[:50])  # 截取前 50 位看看

你看,一下子就得到了一个 1024 位的指纹。这个结构化的向量可以直接喂给神经网络,非常方便。

但要注意:指纹是稀疏的,而且“哈希碰撞”偶尔会发生——两个不同的分子可能映射成相似的指纹。这不是大问题,但你在设计 GAN 的损失函数时,要考虑到这种信息的损失。

核心结论:三种表示各有所长。SMILES 轻便适合 Transformer;分子图保留拓扑结构,是图 GAN 的首选;分子指纹编码子结构信息,适合做判别特征。我个人建议:在你第一个 GAN 版本里,优先使用分子图,然后扩展到混合表示。

知识全景图

下面这张图,帮你把三种表示方法的全局对比和生成任务定位理清楚。不用记,看着有个感觉就行。

分子表示方法对比图 SMILES 分子图 分子指纹 线性文本 节点+边拓扑 固定位向量 GAN 生成任务定位 生成器 判别器 文本模型(RNN/Transformer) 图神经网络(GNN/GAN) 分类器/相似度/判别器 用于生成:分子图 > SMILES > 指纹 | 用于判别:指纹 > SMILES > 分子图

2.4 我该如何选?

其实没有万能答案。但根据我的项目经验,可以给你几个参考:

  1. 如果从零开始,做原型 → 先用 SMILES,接入快,能快速验证 GAN 能不能收敛
  2. 如果追求生成分子的质量 → 必须上分子图。图 GAN 生成的分子结构完整性明显更强
  3. 如果需要判别器判断“像不像药” → 搭配分子指纹,特别是 ECFP4,信息量大且标准
  4. 如果你有余力 → 混合表示:生成器用图,判别器用指纹+SMILES双重特征

嗯,就我个人而言,我现在的标准套路是:生成器用图 GAN,判别器取分子图中节点特征 + MACCS 指纹做联合输入。这个组合在我的项目里效果最稳定。

别急,后面几章我会带你一步步实现这个流程。先把这些基础概念焊牢,后面跑代码才能稳。