2. 分子表示与特征工程

生成模型不会直接“看见”分子,它只能处理张量。因此,分子表示与特征工程决定了模型能学到什么、生成结果是否合法、以及能否被下游任务直接使用。本节围绕四类主流表示——SMILES、SELFIES、分子图、3D构象——说明它们各自适合什么场景,并给出面向生成模型的原子、键、官能团与药效团特征构建方法。

一、四种表示方法的定位与取舍

SMILES 是线性字符串表示,例如 CCO 表示乙醇,c1ccccc1 表示苯环。它的优势是紧凑、易被序列模型(RNN、Transformer)处理,训练成本低;缺点是同一分子存在多种合法写法(如 CC(=O)O 与 OC(C)=O 都是乙酸),且模型生成的字符串可能违反价键规则而无法解析。工程上通常配合 RDKit 做规范化(canonicalization),把同一分子的多种写法统一为唯一形式,降低模型需要学习的冗余模式。

SELFIES 是“自指 SMILES”,其核心设计是:任意由合法符号表拼出的 SELFIES 字符串,解码后一定是合法分子。这从根本上消除了生成无效分子的风险。代价是字符串更长、语义不如 SMILES 直观,且并非所有 SMILES 都能无损转换。实践中常见策略是:用 SELFIES 做生成,再解码回 SMILES 做后续处理。

分子图 把分子显式表示为节点(原子)与边(化学键)的集合,天然保留拓扑结构,适合 GNN、图扩散模型、图 VAE。它避免了序列表示中“长程依赖难建模”的问题,但需要处理节点数可变、批处理对齐等工程细节。

3D构象 在图上叠加原子三维坐标,直接刻画键长、键角、二面角与空间位阻,是结构生成、对接、药效团匹配的基础。代价是构象空间巨大,需要构象采样(如 ETKDG)与能量筛选,计算开销显著高于前三种。

四种分子表示:信息保留与生成适用性对照 SMILES 线性字符串 CCO / c1ccccc1 ✓ 紧凑、序列模型友好 ✗ 写法不唯一、可能非法 需规范化处理 SELFIES 自指字符串 [C][C][O] ✓ 解码必合法 ✗ 更长、转换有损 适合生成阶段 分子图 节点+边 原子 / 化学键 ✓ 拓扑显式、GNN友好 ✗ 变长、批处理复杂 适合图生成模型 3D构象 图+坐标 (x, y, z) 原子坐标 ✓ 含空间信息 ✗ 构象空间大、开销高 适合结构生成/对接 面向生成模型的特征构建:从分子到张量 原子特征 元素类型(C/N/O…) 度、形式电荷、杂化 是否在环、手性标签 键特征 键类型(单/双/三/芳) 共轭、是否在环 立体化学(E/Z) 官能团特征 羟基、羧基、氨基 卤素、硝基、酯基 SMARTS 子结构匹配 药效团特征 氢键供体/受体 疏水中心、芳香环 正/负电中心

二、原子与键特征:生成模型的最小输入单元

无论用图还是序列,原子和键都是最基础的建模对象。原子特征通常编码为定长向量,常用字段包括:元素类型(one-hot 或嵌入)、原子度(连接数)、形式电荷、杂化方式(sp/sp²/sp³)、是否在环上、手性标签(R/S)。键特征则包括键类型(单键、双键、三键、芳香键)、是否共轭、是否在环上、以及 E/Z 立体标记。

以 RDKit 为例,从 SMILES 构建图特征的核心代码如下:

from rdkit import Chem
import numpy as np

def atom_features(atom):
    return np.array([
        atom.GetAtomicNum(),                    # 原子序数
        atom.GetDegree(),                       # 度
        atom.GetFormalCharge(),                 # 形式电荷
        int(atom.GetIsAromatic()),              # 是否芳香
        int(atom.IsInRing()),                   # 是否在环
        int(atom.GetChiralTag())                # 手性标签
    ], dtype=np.float32)

def bond_features(bond):
    bt = bond.GetBondType()
    return np.array([
        int(bt == Chem.BondType.SINGLE),
        int(bt == Chem.BondType.DOUBLE),
        int(bt == Chem.BondType.TRIPLE),
        int(bt == Chem.BondType.AROMATIC),
        int(bond.GetIsConjugated()),
        int(bond.IsInRing())
    ], dtype=np.float32)

mol = Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O")  # 阿司匹林
for atom in mol.GetAtoms():
    print(atom.GetIdx(), atom_features(atom))

这段代码把阿司匹林转化为“节点特征矩阵 + 边特征矩阵”,可直接送入 GNN。注意:原子序数等连续量建议做归一化或改用嵌入层,避免数值尺度差异影响训练稳定性。

三、官能团与药效团:从原子级到语义级

原子和键特征描述的是“局部化学环境”,但生成模型若只学这些,容易生成化学上合法、功能上无意义的分子。官能团特征把分子拆解为羟基、羧基、氨基、卤素、硝基、酯基等语义单元,常用 SMARTS 模式匹配实现。例如羧基可用 [CX3](=O)[OX2H1] 匹配,芳香环可用 c1ccccc1 匹配。匹配结果可编码为“官能团存在向量”或“每个原子的官能团归属标签”,作为额外节点特征拼接到原子特征上。

药效团特征更进一步,关注的是分子与靶点结合所需的抽象性质:氢键供体(HBD)、氢键受体(HBA)、疏水中心、芳香环、正电中心、负电中心。药效团不依赖具体原子类型,而是用“特征点 + 空间距离”描述结合模式,因此特别适合 3D 生成模型和骨架跃迁任务。工程上可用 RDKit 的 ChemicalFeatures 模块或 Pharmit 等工具提取药效团指纹。

实践建议:特征并非越多越好。原子+键特征适合大多数图生成模型;官能团特征适合需要控制产物类别的条件生成;药效团特征适合以靶点结合为导向的 3D 生成。建议先用最小特征集跑通基线,再按任务需求逐步增加特征维度,并监控验证集上的生成合法率与新颖性。

四、3D构象的生成与筛选

3D 表示的关键是构象生成。以 RDKit 的 ETKDG 方法为例,给定 SMILES 后可生成多个候选构象,再用 MMFF94 力场做能量最小化,最后按能量排序保留低能构象:

from rdkit import Chem
from rdkit.Chem import AllChem

mol = Chem.AddHs(Chem.MolFromSmiles("CCO"))
params = AllChem.ETKDGv3()
params.randomSeed = 42
cids = AllChem.EmbedMultipleConfs(mol, numConfs=10, params=params)
results = AllChem.MMFFOptimizeMoleculeConfs(mol)
# results: [(converged, energy), ...]
for i, (conv, energy) in enumerate(results):
    print(f"构象 {i}: 收敛={conv}, 能量={energy:.2f} kcal/mol")

示例输出中,能量最低且收敛的构象通常作为后续 3D 生成模型的训练目标。需要注意:构象生成具有随机性,应固定随机种子以保证可复现;同时要检查生成的构象是否出现原子重叠或异常键长,必要时用 AllChem.MMFFHasAllMoleculeParams 确认力场参数覆盖完整。

五、表示与特征的组合策略

实际项目中,四种表示往往组合使用。一种常见架构是:用 SELFIES 或 SMILES 做序列生成,解码为分子图后提取原子/键/官能团特征,再用 3D 构象模块做结构精修与打分。这种“序列生成 + 图特征校验 + 3D 筛选”的流水线,兼顾了生成效率与化学合理性。

表示方法 信息保留 生成合法性 计算开销 典型模型
SMILES 拓扑+部分立体 可能非法 低 RNN、Transformer
SELFIES 拓扑+部分立体 必合法 低 Transformer、VAE
分子图 拓扑完整 需约束 中 GNN、图扩散
3D构象 拓扑+空间 需能量筛选 高 扩散模型、Flow

选择表示方法时,先明确任务目标:若追求生成速度与多样性,优先 SMILES/SELFIES;若需要精确控制拓扑与子结构,优先分子图;若涉及靶点结合或立体选择性,必须引入 3D 构象。特征工程则围绕“原子—键—官能团—药效团”四个层级逐步构建,每一层都应有明确的化学含义和可验证的提取方式,避免把无关数值堆进特征向量。