2. 分子图数据构建与清洗
分子图模型的第一道工程关口不是模型结构,而是数据。一个分子在磁盘上可能以 SMILES 字符串、SDF 记录块或 MOL2 文本存在,但模型真正消费的是“节点特征矩阵 + 边索引 + 边特征”这一组张量。本节围绕这条转换链展开:先解析成带三维或二维坐标的分子对象,再抽取原子与键特征,最后做去重、标准化与缺失值处理,得到可训练、可复现的图数据集。
一、三种格式的解析差异与统一中间表示
SMILES 是线性字符串,解析快、体积小,但它默认只携带拓扑与元素信息,不含显式氢原子和坐标。以 RDKit 为例,Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O") 得到的是重原子图,氢原子被隐式处理,需要 Chem.AddHs() 才能显式化。SDF 是记录式格式,每条记录包含原子块、键块和属性块,通常带 2D 或 3D 坐标,适合直接构建带几何信息的图。MOL2 常见于对接与动力学输出,原子类型采用 Tripos 命名,键级信息有时缺失,需要按距离或化学规则补全。
工程上不建议让下游代码直接面对三种格式,而应统一为中间表示:原子列表(元素、坐标、形式电荷、芳香性、手性)、键列表(起止原子索引、键级、是否共轭、是否成环)、以及分子级属性(分子量、logP、来源 ID)。这样后续特征工程只写一套逻辑。
from rdkit import Chem
def parse_any(path):
if path.endswith(".sdf"):
supp = Chem.SDMolSupplier(path, removeHs=False)
return [m for m in supp if m is not None]
if path.endswith(".mol2"):
return [Chem.MolFromMol2File(path, removeHs=False)]
if path.endswith(".smi"):
mols = []
for line in open(path):
smi = line.split()[0]
m = Chem.MolFromSmiles(smi)
if m: mols.append(Chem.AddHs(m))
return mols
raise ValueError("unsupported format")
注意 removeHs=False 与 AddHs() 的取舍:若模型需要显式氢(如某些反应性预测),必须保留;若只做性质回归,隐式氢可显著减小图规模。这一决定要在数据构建阶段固定,不能训练时再变。
二、原子与键特征工程
原子特征通常包括:元素类别(one-hot 或嵌入索引)、度、形式电荷、杂化类型、是否芳香、是否在环内、手性标签、以及可选的坐标。键特征包括:键级(单/双/三/芳香)、是否共轭、是否成环、立体构型、键长。特征维度一旦确定,就要写入配置并随数据集版本一起保存,否则不同批次数据会因特征顺序不一致而静默出错。
下面是一个可复用的原子特征抽取示例,输出固定长度向量:
ATOM_TYPES = ["C","N","O","S","F","Cl","Br","I","P","Other"]
def atom_features(atom):
return [
ATOM_TYPES.index(atom.GetSymbol()) if atom.GetSymbol() in ATOM_TYPES else ATOM_TYPES.index("Other"),
atom.GetDegree(),
atom.GetFormalCharge(),
int(atom.GetIsAromatic()),
int(atom.IsInRing()),
int(atom.GetChiralTag()),
]
键特征同理,用 bond.GetBondType()、bond.GetIsConjugated()、bond.IsInRing() 映射为整数或 one-hot。若使用 3D 坐标,键长可由两原子坐标欧氏距离计算,并做标准化(减去均值、除以标准差),否则不同来源的坐标尺度差异会干扰模型。
三、去重、标准化与缺失值处理
去重不能只比较 SMILES 字符串,因为同一分子可能有多种合法写法。推荐用 InChIKey 作为唯一标识:Chem.MolToInchiKey(mol)。若数据来自多个供应商,还要先做盐剥离与电荷中和,否则同一活性分子的盐酸盐与游离碱会被当成两条记录。标准化流程可固定为:去盐 → 中和电荷 → 统一互变异构体(可选)→ 生成 InChIKey → 按 InChIKey 去重。
缺失值分三类处理。第一类是标签缺失,通常直接丢弃或放入无监督预训练集,不能填 0 后混入回归训练。第二类是原子/键特征缺失,例如 MOL2 缺键级,可用距离阈值补全,或增加“未知”类别并保留掩码位。第三类是坐标缺失,SMILES 来源没有 3D 坐标,若模型依赖几何,需要用 ETKDG 等构象生成方法补齐,并记录“坐标为生成值”这一来源标记,避免与实验晶体结构混用。
四、可复现的数据构建检查清单
为了让数据构建可复现,建议在每次生成数据集时输出一份元数据记录,至少包含:源文件路径与哈希、解析器版本、是否加氢、特征维度与顺序、去重前后数量、标准化规则、缺失值策略、随机种子。下面给出一个可直接参考的记录结构:
{
"source": "chembl_30.sdf",
"source_sha256": "a1b2c3...",
"parser": "rdkit-2023.09",
"add_hs": true,
"atom_feat_dim": 6,
"bond_feat_dim": 4,
"n_raw": 12000,
"n_after_dedup": 11340,
"standardize": ["desalt", "neutralize", "inchikey"],
"missing_policy": "mask",
"seed": 42
}
实际执行时,建议先在小样本(如 200 条)上跑通全链路,检查原子数分布、键数分布、特征取值范围是否合理,再放大到全量。常见异常包括:解析失败率突然升高(多为编码或格式混用)、芳香键被误判为单双键交替、以及去重后数量骤降(多为盐剥离规则过激)。这些都要在数据版本发布前定位并记录。
完成本节后,你应当能够把任意来源的分子文件转成统一的图数据集,并说清每一步对最终张量的影响。下一阶段才是在此基础上划分训练/验证/测试集并设计模型。