3. 分子表示方法:SMILES、分子图、3D坐标、描述符
做分子生成,第一关就是“怎么让计算机看懂分子”。不同表示方法,就像不同语言——有的适合写诗,有的适合算账。分布式训练下,选错表示可能让通信开销翻倍,GPU利用率惨不忍睹。我踩过这个坑,所以先把几种主流方法给你拆清楚。
3.1 SMILES – 最轻量的字符串
SMILES用一串字符描述原子、键、分支和环。比如乙醇写CCO,苯环写c1ccccc1。优点是极简,一个字符串就能扔进Transformer或RNN。但你想想看,同一个分子可能有多种合法SMILES——这叫“规范性问题”。
我在项目里遇到过:两个团队分别生成SMILES,送去训练后模型死活学不对,一查发现各自用的规范化规则不同。后来我们统一用RDKit的Chem.MolToSmiles加canonical参数,才把坑填平。
from rdkit import Chem
mol = Chem.MolFromSmiles("CCO")
canonical_smiles = Chem.MolToSmiles(mol) # 输出 "CCO"
print(canonical_smiles)
3.2 分子图 – 保留拓扑结构
分子图把原子当节点,化学键当边。每个节点可带特征(原子类型、电荷、杂化),边可带特征(键级、芳香性)。图神经网络(GNN)天然适合这种输入,消息传递过程就是模拟化学环境的“感知”。
我用过DGL和PyG两个框架,个人习惯选PyG,因为它的DataLoader对分布式训练支持更直接。但要注意,稀疏邻接矩阵在跨GPU通信时,必须处理边索引的重新编号。我曾经没处理好,导致每个GPU看到的图都不一样——模型直接崩溃。
from torch_geometric.data import Data
import torch
# 分子水:一个氧,两个氢,两根单键
edge_index = torch.tensor([[0, 0], [1, 2]], dtype=torch.long) # (2, num_edges)
x = torch.tensor([[8], [1], [1]], dtype=torch.float) # 原子序数
data = Data(x=x, edge_index=edge_index)
3.3 3D坐标 – 空间全貌
3D坐标给出每个原子的三维位置(单位Å)。常用于构象生成、结合能预测、力场模拟。表示方法很直白:原子列表 + 坐标矩阵。常用格式:SDF、XYZ。
但有个大坑:分子构象不是唯一的!同一个分子可能有几十个稳定构象。你训练用的构象和推理用的构象不匹配,模型效果就会漂移。我建议:在数据处理阶段固定构象生成流程(比如用ETKDG加力场优化),并记录每个分子的“代表性构象”。
# 乙醇的XYZ格式示例(部分)
C 0.0000 0.0000 0.0000
C 1.5100 0.0000 0.0000
O 1.9900 1.2600 0.0000
H -0.3800 -0.3800 0.9400
...
3.4 分子描述符 – 数值化捷径
描述符是预计算的特征向量,比如分子量(MW)、脂水分配系数(LogP)、拓扑极性表面积(TPSA)、氢键供体数、旋转键数等。传统定量构效关系(QSAR)全靠它,现代分子生成也常把它作为条件约束或辅助损失。
说实话,描述符计算很简单:调用rdkit.Chem.Descriptors即可。但不同软件的结果可能有细微差异——我曾经用两个工具算同一个分子的LogP,差了0.3。后来我们规定全局只用RDKit 2021.03版本,统一计算库,才消掉这个偏差。
from rdkit.Chem import Descriptors
mol = Chem.MolFromSmiles("CCO")
mw = Descriptors.MolWt(mol) # 46.07
logp = Descriptors.MoLogP(mol) # -0.14
tpsa = Descriptors.TPSA(mol) # 20.23
3.5 四种表示对比
| 表示方法 | 维度 | 数据量(典型) | 分布式难点 | 适用场景 |
|---|---|---|---|---|
| SMILES | 序列 (30–150 tokens) | 极小 | 长度padding浪费 | Seq2Seq生成、语言模型 |
| 分子图 | 图 (节点+边) | 中 | 稀疏通信、重新编号 | GNN、反应预测 |
| 3D坐标 | 3×N 矩阵 | 大 (×3 float) | IO瓶颈、构象对齐 | 构象生成、物理对接 |
| 描述符 | 固定长度 (几十~几百) | 极小 | 计算一致性 | 条件生成、辅助损失 |
3.6 实际选型建议
做多GPU分布式训练时,我通常按这个思路判断:
- 优先SMILES:如果你的任务目标是生成新分子,且GPU集群带宽高(如NVLink),SMILES最省计算,Transformer直接上。
- 分子图做主表示:需要理解分子局部结构(如官能团)时,图比序列更直观。注意用PyG的
DistributedNeighborSampler缓解边索引同步压力。 - 3D坐标当额外输入:只有涉及构象或几何性质时才上。配合等变网络(如SE(3)-Transformer),计算开销翻倍,但精度提升明显。
- 描述符做条件:不管主表示是什么,加几个描述符约束能稳定训练。我常把LogP、TPSA拼到多模态输入里。
说到底,分子表示是分布式训练的“地基”。地基不稳,再漂亮的网络结构也白搭。我个人建议:团队先统一表示标准、数据处理流水线,再考虑分布式加速。磨刀不误砍柴工,这个习惯帮我省了不知道多少debug时间。