3. 数据工程基础

在生成式分子设计项目中,模型的上限往往不由网络结构决定,而由数据决定。一个 SMILES 序列模型、图生成模型或扩散模型,如果训练集里混入了盐离子、同位素标记、互变异构体重复、错误价态和来源偏倚,生成结果就会系统性地偏向这些噪声。数据工程的目标不是“把数据变干净”这么笼统,而是建立一条可复现的流水线:从来源采集,到结构解析、标准化、去重、质量打分,最终产出可追溯、可版本化的训练集。

一、分子数据从哪里来

常见来源可分为四类。第一类是公共化合物库,如 ChEMBL、PubChem、ZINC、DrugBank,它们提供 SMILES、InChI、活性值和物化属性,适合做条件生成与性质预测。第二类是文献与专利抽取数据,如 Reaxys、SureChEMBL,覆盖反应与新颖骨架,但噪声高、格式杂。第三类是计算生成数据,包括对接构象、DFT 优化几何、分子动力学轨迹,适合做三维生成与能量相关任务。第四类是自有实验数据,如内部合成记录、HPLC/MS 表征、活性测试表,价值最高但规模小、字段不统一。

采集时必须同时记录来源标识、许可协议、采集时间、原始文件哈希。缺少这些元数据,后续无法做数据溯源,也无法在模型出问题时定位是哪个批次引入的偏差。

二、清洗:从原始记录到可解析结构

清洗的第一步是结构可解析性检查。用 RDKit 读取每条 SMILES,捕获解析异常:

from rdkit import Chem
from rdkit import RDLogger
RDLogger.DisableLog('rdApp.*')

def parse_smiles(smi):
    mol = Chem.MolFromSmiles(smi)
    if mol is None:
        return None, "parse_error"
    if mol.GetNumAtoms() == 0:
        return None, "empty_mol"
    return mol, "ok"

第二步是去除无关成分。多数库中的记录是盐、溶剂化物或混合物,需要保留最大有机片段,并记录被剥离的 counterion。常用做法是 rdMolStandardize.FragmentParent 或按重原子数选取主片段。第三步是元素与价态过滤:剔除含金属、硼酸酯保护基、异常价态原子、自由基的条目,除非任务本身需要。第四步是规模过滤,例如限制重原子数在 10–50、分子量 150–600,避免极端分子主导分布。

三、标准化:让同一分子只有一种表示

标准化解决“同一分子多种写法”的问题。核心操作包括:去质子化/质子化归一(中性化)、互变异构体归一、电荷归一、立体化学保留策略、芳香性感知统一。RDKit 提供 rdMolStandardize 模块,典型流程为:

from rdkit.Chem.MolStandardize import rdMolStandardize

uncharger = rdMolStandardize.Uncharger()
te = rdMolStandardize.TautomerEnumerator()
te.SetMaxTautomers(1000)

def standardize(mol):
    mol = uncharger.uncharge(mol)          # 电荷归一
    mol = te.Canonicalize(mol)             # 互变异构归一
    Chem.AssignStereochemistry(mol, cleanIt=True, force=True)
    return Chem.MolToSmiles(mol, isomericSmiles=True, canonical=True)

需要注意:互变异构归一可能改变某些任务的正确答案,例如涉及酮-烯醇互变的反应预测。因此标准化策略必须与下游任务绑定,并在数据卡中明确写出“是否做了互变异构归一”。

四、去重:从字符串到结构再到骨架

去重不能只比较原始 SMILES 字符串,因为同一分子可能有多种合法写法。正确顺序是:先标准化,再生成规范 SMILES,再做精确去重;随后用 InChIKey 的前 14 位做骨架级去重,识别同一骨架的不同取代;最后可用 Bemis-Murcko 骨架或 ECFP4 指纹相似度(如 Tanimoto > 0.85)做近重复聚类,防止训练/验证集泄漏。

划分训练/验证/测试集时,应按骨架或聚类划分,而不是随机按分子划分。随机划分会让高度相似的类似物同时出现在训练和测试中,导致指标虚高。

五、质量评估与数据卡

质量评估应给出可量化指标:解析成功率、标准化后唯一分子数、去重率、重原子数分布、分子量分布、LogP 分布、电荷分布、立体中心比例、骨架多样性(唯一 Murcko 骨架数 / 总分子数)、以及来源占比。这些指标应写入数据卡,与数据集版本一起冻结。

下面这张图概括了从多源采集到训练集的完整数据流,以及每一步的关键操作与产出物。

分子数据工程流水线:来源 → 清洗 → 标准化 → 去重 → 质量评估 公共化合物库 ChEMBL / PubChem ZINC / DrugBank SMILES + 活性 + 属性 元数据:来源/许可/哈希 文献与专利抽取 Reaxys / SureChEMBL 反应 + 新颖骨架 噪声高、格式杂 需人工抽检 计算生成数据 对接构象 / DFT 几何 MD 轨迹 三维坐标 + 能量 适合 3D 生成任务 自有实验数据 合成记录 / HPLC-MS 活性测试表 价值高、规模小 字段不统一 ① 清洗 Clean RDKit 解析 → 去盐/去溶剂 → 价态与元素过滤 产出:可解析分子 + 失败原因标签 ② 标准化 Standardize 电荷归一 → 互变异构归一 → 立体化学统一 产出:规范 SMILES + InChIKey ③ 去重 Deduplicate 规范 SMILES 精确去重 → InChIKey 骨架去重 → ECFP4 近重复聚类(Tanimoto > 0.85) ④ 质量评估与数据卡 • 解析成功率 / 去重率 • 重原子数、MW、LogP 分布 • 电荷与立体中心比例 • 骨架多样性 = 唯一骨架/总数 • 来源占比与批次哈希 产出:冻结版本训练集 + 数据卡 训练 / 验证 / 测试集(按骨架或聚类划分)

六、一个可执行的质量检查清单

把上述流程固化为检查表,可以在每次数据更新时快速复核:

检查项判断标准(示例)不通过时的处理
SMILES 解析成功率≥ 99%回溯原始文件,定位异常批次
标准化后唯一分子占比记录去重率,通常 5%–30%检查是否漏做互变异构归一
重原子数范围10–50过滤极端分子或单独建子集
骨架多样性唯一 Murcko 骨架 / 总分子 ≥ 0.3补充多样来源或做聚类重采样
训练/测试骨架重叠重叠率 = 0按骨架重新划分
来源占比单一来源 ≤ 70%调整采样权重或补充数据
标准化与去重会不可逆地改变数据。务必保留原始数据与标准化脚本,并把脚本版本、参数、随机种子写入数据卡。否则当模型效果异常时,无法判断是数据问题还是模型问题。

完成这一节的工作后,你应当得到三样东西:一份可复现的清洗与标准化脚本、一份冻结版本的训练集、一份记录关键统计量与来源的数据卡。它们共同构成后续特征工程、模型训练与评估的可信基础。