4. 分子表征与特征工程
毒性预测模型的性能上限,往往在特征工程阶段就已经被决定。同一个随机森林或图神经网络,输入不同的分子表征,AUC 可能相差 0.15 以上。本节围绕“把分子变成模型可读的数值向量”这一核心任务,梳理四类主流表征方式及其适用边界,并给出面向毒性预测的特征选择与验证流程。
一、四类分子表征的本质差异
分子指纹是基于子结构的哈希或计数向量。以 Morgan/ECFP 为例,算法从每个重原子出发,按半径 r 迭代扩展邻域,将每层子结构哈希到固定长度位串(如 2048 位)。r=2 对应直径 4 的邻域,能捕捉官能团级别的局部环境。MACCS Keys 则是 166 位预定义子结构字典,可解释性强但覆盖有限。指纹的优点是计算快、对局部毒性基团(如硝基、环氧化物、酰卤)敏感;缺点是丢失立体化学与长程拓扑信息。
分子描述符是可解释的物理化学量。RDKit 的 Descriptors 模块可计算约 200 个描述符,毒性建模中高频使用的包括:MolWt(分子量)、MolLogP(脂水分配系数)、TPSA(拓扑极性表面积)、NumHDonors/NumHAcceptors(氢键供受体数)、NumAromaticRings(芳环数)、FractionCSP3(sp³ 碳比例)、MaxPartialCharge(最大部分电荷)。这些量直接关联 ADMET 性质:LogP > 5 且 TPSA < 75 的化合物更易穿透生物膜并蓄积,肝毒性风险上升;FractionCSP3 偏低常与 hERG 抑制相关。
图表示把分子视为原子为节点、化学键为边的属性图。节点特征通常为原子类型、度、形式电荷、杂化方式、是否在环内;边特征为键型(单/双/三/芳香)、是否共轭、是否在环内。GNN 通过消息传递聚合邻域信息,天然保留拓扑与立体信息,适合捕捉“毒性由特定子图组合触发”的模式,但需要更多数据且可解释性弱于描述符。
SMILES 嵌入将一维字符串映射为连续向量。早期用字符级 n-gram 或 TF-IDF,现在多用预训练语言模型(如 ChemBERTa、MolFormer)或 SMILES 枚举增强。其优势是能利用大规模无标注数据,对训练集未出现的骨架有一定泛化;风险是嵌入空间缺乏化学约束,可能出现“相似向量、迥异结构”的伪相似。
二、面向毒性预测的特征选择实操
把四类表征简单拼接会得到数千维特征,直接训练极易过拟合。以下流程以“肝毒性二分类”为例,训练集 1200 个化合物、测试集 300 个,正负比约 1:3。
第一步:方差与缺失过滤。剔除方差接近 0 的位(如所有分子都不含某子结构)和缺失率 > 20% 的描述符。RDKit 计算的部分描述符在含金属原子时可能返回 NaN,需显式处理。
第二步:相关性去冗余。计算描述符间 Pearson 相关系数,对 |r| > 0.95 的特征对,保留与标签互信息更高者。例如 MolWt 与 NumHeavyAtoms 高度相关,通常保留 MolWt。
第三步:基于模型的重要性排序。用随机森林(500 棵树,max_depth=12)拟合,输出 feature_importances_。典型结果中,MolLogP、TPSA、NumAromaticRings、Morgan 指纹中对应“芳香胺/硝基”的位往往排在前列。取重要性累计贡献 95% 的特征子集。
第四步:递归特征消除(RFE)与交叉验证。以 5 折交叉验证的 AUC 为准则,逐步剔除最不重要特征。示例中,从 2048+200 维降至约 180 维时,验证集 AUC 从 0.78 升至 0.84;继续降至 50 维以下则 AUC 回落,说明存在信息损失。
from rdkit import Chem
from rdkit.Chem import AllChem, Descriptors
import numpy as np
def featurize(smiles):
mol = Chem.MolFromSmiles(smiles)
if mol is None:
return None
# Morgan 指纹 2048 位
fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)
fp_arr = np.array(fp)
# 关键描述符
desc = np.array([
Descriptors.MolWt(mol),
Descriptors.MolLogP(mol),
Descriptors.TPSA(mol),
Descriptors.NumHDonors(mol),
Descriptors.NumHAcceptors(mol),
Descriptors.NumAromaticRings(mol),
Descriptors.FractionCSP3(mol),
])
return np.concatenate([fp_arr, desc])
# 示例: 对乙酰氨基酚
vec = featurize("CC(=O)Nc1ccc(O)cc1")
print(vec.shape) # (2055,)
三、表征选择与验证的判断依据
选择哪类表征,取决于数据规模、可解释性要求和毒性终点。数据量 < 500 时,优先描述符 + MACCS,避免 GNN 过拟合;数据量 > 5000 且毒性机制涉及复杂子图组合时,图表示或 SMILES 嵌入更有优势。若监管场景要求解释“为什么预测有毒”,描述符和指纹位可直接映射到官能团,而 GNN 需借助 GNNExplainer 等事后解释工具。
验证环节必须使用骨架划分(scaffold split)而非随机划分。随机划分会让同一骨架的类似物同时出现在训练和测试集,导致 AUC 虚高。以 Bemis-Murcko 骨架分组后,测试集 AUC 通常比随机划分低 0.05~0.12,这个差值才是模型真实泛化能力的体现。