分子表示基础:SMILES字符串、分子图、分子指纹与向量化方法
做分子生成,第一个绕不开的问题就是:怎么让深度学习模型"看懂"分子?
你不能直接把一个分子结构图扔给神经网络。模型只吃数字,不吃结构式。所以,我们需要把分子转成计算机能处理的形式。这就是分子表示。
我个人习惯把分子表示分成四个流派:字符串派(SMILES)、图流派(分子图)、指纹派(分子指纹)和向量派(向量化方法)。每个流派都有自己的脾气,咱们一个一个聊。
1. SMILES字符串——分子的"一行诗"
SMILES全称是Simplified Molecular Input Line Entry System。说白了,就是把分子结构写成一行字符串。我刚开始接触时觉得挺神奇——一个苯环居然能用 c1ccccc1 六个字符搞定。
SMILES的规则其实不复杂:
- 原子用元素符号表示:C(碳)、O(氧)、N(氮)、c(芳香碳)等。
- 单键直接连,双键用
=,三键用#。 - 分支用括号
(),比如乙醇CCO没分支,但异丙醇就是CC(C)O。 - 环用数字标记,比如苯环
c1ccccc1,数字1首尾配对。
举个例子,阿司匹林的SMILES长这样:
CC(=O)Oc1ccccc1C(=O)O
你看,括号、等号、数字全用上了。这串字符虽然看着乱,但模型非常爱吃。
Chem.MolToSmiles() 默认就是标准输出。
@ 或 @@ 标记,初学者容易漏掉。我曾经在一次生成任务中,因为没处理手性标记,生成的分子有一半是镜像异构体……
2. 分子图——从拓扑角度看分子
分子本质上是图结构。原子是节点,化学键是边。这个视角非常自然,也很适合图神经网络(GNN)。
用RDKit构建分子图非常方便:
from rdkit import Chem
from rdkit.Chem import rdmolops
mol = Chem.MolFromSmiles("CCO")
adj_matrix = rdmolops.GetAdjacencyMatrix(mol)
print(adj_matrix)
# [[0 1 0]
# [1 0 1]
# [0 1 0]]
你看,乙醇的邻接矩阵就是3x3,碳碳单键相连,碳氧单键相连。
分子图的核心信息包括:
- 节点特征:原子类型(C、O、N...)、杂化方式、电荷、手性等。
- 边特征:键类型(单键、双键、三键、芳香键)、键长、是否在环中等。
我在做分子性质预测项目时,用过GIN(Graph Isomorphism Network)处理分子图。效果确实好,但图的大小不一致是个麻烦——乙醇只有3个原子,阿司匹林有21个,你得做padding或者batch处理。
3. 分子指纹——结构的二进制编码
分子指纹,说白了就是一个固定长度的二进制向量。每一位代表一个子结构是否存在。最早的是MACCS指纹,166位,每个位对应一个预定义的子结构模式。
但MACCS太"死"了。现在更常用的是ECFP(Extended Connectivity Fingerprint),也叫摩根指纹。它不预定义子结构,而是从每个原子出发,逐层扩展邻居,生成哈希特征。
ECFP的生成过程我简单说一下:
- 对每个原子,根据其类型、度数、电荷等计算一个初始标识符。
- 逐层融合邻居的标识符,生成新的特征。
- 把最终的特征哈希到固定长度的位向量里。
用RDKit算ECFP只需几行代码:
from rdkit import Chem
from rdkit.Chem import AllChem
mol = Chem.MolFromSmiles("CCO")
ecfp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)
print(ecfp.ToBitString()[:50])
# 00100101001001100100101001001001001001001001100100
2048位的向量,每一位是0或1。这就是分子指纹。
4. 向量化方法——让分子走进深度学习
SMILES是字符串,分子图是图结构,分子指纹是二进制向量。深度学习模型要的是连续值向量。怎么转?
常见做法有以下几种:
- One-hot编码:对SMILES字符集做one-hot。简单但维度爆炸,且丢失了字符之间的关联。
- Embedding层:把SMILES字符映射到低维稠密向量。这是主流做法,能学到字符的语义关系。
- 分子指纹直接作为向量:ECFP的2048位向量本身就是特征,但稀疏且离散,很多模型吃不下。
- 图读出(Graph Readout):用GNN提取分子图的全局特征向量,比如对节点特征做 sum/mean/max pooling。
我个人的建议是:
- 如果用序列模型(RNN/Transformer),走SMILES + Embedding路线。
- 如果用图神经网络,直接用分子图 + Readout。
- 如果用传统ML模型(随机森林、SVM),用分子指纹。
对占比分子生成来说,SMILES + Embedding 和 分子图 + GNN 是两条主流路线。我本人更倾向后者——图结构保留了完整的拓扑信息,不容易被SMILES的语法陷阱误导。
5. 四种表示方法的对比与选择
我把它们整理成一张表,方便你对比:
| 表示方法 | 数据形式 | 维度 | 是否保留拓扑 | 适合模型 | 缺点 |
|---|---|---|---|---|---|
| SMILES | 字符串 | 可变长度 | 间接保留 | RNN, Transformer | 语法敏感,有无效序列风险 |
| 分子图 | 图结构 | 可变(节点+边) | 直接保留 | GNN, GCN, GAT | 图大小不一,需要padding |
| 分子指纹 | 二进制向量 | 固定(如2048) | 部分保留 | 随机森林, SVM | 信息有损,不可逆 |
| 向量化方法 | 稠密向量 | 固定(如128/256) | 取决于来源 | 全连接, 各类深度学习 | 需要额外训练Embedding |
你想想看,选哪种表示,其实取决于你的模型和任务。我做分子生成,大部分时间都在跟SMILES和分子图打交道。指纹嘛,更多用在虚拟筛选和相似度搜索上。