4.3 特征选择与降维 本节摘要:描述符矩阵动辄上百列,冗余与噪声并存——直接喂给模型会放大过拟合,直接画图会淹没在人眼看不懂的高维里。本节给出特征瘦身的两条主线(选择与降维)及各自的工程取舍,并用"采购库与内部库化学空间对比"的完整案例演示主成分分析的标准用法。 索引卡片房的最后一课:卡片太多与卡片太少一样糟糕。本节承接 4.1 的描述符矩阵与 4.2 的指纹衍生特征,解决它们的共性问题——维度灾难,并为第5、6章备好干净的特征桌面。 描述符太多反而坏事 高维特征的害处有三层,一层比一层隐蔽。表层是冗余:分子量与重原子数相关系数轻松超过零点九,两个都留等于把同一信息数两遍,模型会莫名偏爱它。中层是噪声积累:每列描述符都有自己的测量或计算误差,列数一多,噪声指望"稀释"信号而非被平均掉。
本节摘要:描述符矩阵动辄上百列,冗余与噪声并存——直接喂给模型会放大过拟合,直接画图会淹没在人眼看不懂的高维里。本节给出特征瘦身的两条主线(选择与降维)及各自的工程取舍,并用"采购库与内部库化学空间对比"的完整案例演示主成分分析的标准用法。
索引卡片房的最后一课:卡片太多与卡片太少一样糟糕。本节承接 4.1 的描述符矩阵与 4.2 的指纹衍生特征,解决它们的共性问题——维度灾难,并为第5、6章备好干净的特征桌面。
高维特征的害处有三层,一层比一层隐蔽。表层是冗余:分子量与重原子数相关系数轻松超过零点九,两个都留等于把同一信息数两遍,模型会莫名偏爱它。中层是噪声积累:每列描述符都有自己的测量或计算误差,列数一多,噪声指望"稀释"信号而非被平均掉。底层是过拟合通道:特征列数逼近样本数时,模型几乎总能找到一条恰好拟合训练集的超平面——第6章 QSAR 教训清单里,"特征太多样本太少"常年排在榜首。
处理路线有两条,哲学相反。特征选择从原列里挑子集,保留语义(挑剩的列还是"logP"),但组合爆炸,需要启发式;降维把原列投影成新轴(如主成分),信息浓缩但新轴无语义("主成分一"是什么,要回 4.1 的坐标系里找解释)。工业实践常两条并用:先用过滤法砍掉明显无用的,再视需求决定要不要投影。
三条选择路线各有地盘。过滤法与模型无关,按统计指标打分:方差阈值(几乎不变的列没信息)、相关性去冗余(两列高度相关留一列)、互信息(与目标的非线性关联);快,但看不见特征组合。包裹法拿模型当尺子:递归特征消除反复训练、砍掉最不重要列,效果好但训练成本翻倍。嵌入法让模型顺手挑:带 L1 正则的线性模型会把不重要系数压成零,树模型的特征重要性是现成排序——一次训练两份产出,最划算,代价是与具体模型绑定。
背景。采购部门打算引进一家供应商的化合物库,药化同事担心它和内部库"长得一样"——重叠区买回来是浪费,空白区才是增量。回答这个问题需要把两库放进同一坐标系看分布,这就是化学空间图的标准应用。
操作。两库各取样例,统一计算描述符、标准化、主成分投影到二维:
import numpy as np from rdkit import Chem from rdkit.Chem import rdMolDescriptors as rd from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA def descriptor_table(smiles_list): rows = [] for s in smiles_list: m = Chem.MolFromSmiles(s) if m is None: continue rows.append([ rd.CalcExactMolWt(m), rd.CalcTPSA(m), rd.CLogP(m) if hasattr(rd, "CLogP") else rd.CalcCrippenDescriptors(m)[0], rd.CalcNumRotatableBonds(m), rd.CalcNumRings(m), ]) return np.array(rows) X_in = descriptor_table(internal_library) # 内部库样例 X_vnd = descriptor_table(vendor_library) # 供应商库样例 X_all = StandardScaler().fit_transform(np.vstack([X_in, X_vnd])) xy = PCA(n_components=2).fit_transform(X_all) print("两主成分累计解释率:%.0f%%" % ( 100 * PCA(n_components=2).fit(X_all).explained_variance_ratio_.sum())) # 把 xy 前 len(X_in) 行当内部库、其余当供应商库,画散点即可见重叠与空白
结果。典型输出里,前两个主成分合计解释四成到六成方差——对描述符数据这算合格;散点图上两库云团大部分交叠,但供应商库在"高脂水、低极性"方向多出一块内部库没有的云区。
解读。两处判读要点。其一,解释率不高是常态不必恐慌:描述符矩阵的相关结构本来分散,二维图的价值在比较分布形态而非穷尽信息;要看更细可用三维图或换 UMAP,但投影方法的"形状伪影"要心里有数——它擅长展示局部抱团,不保证全局距离成比例。其二,发现空白区不等于该补:先查那片空白是化学空间的荒漠(不稳定、不可合成),还是内部历史偏好造成的空置——描述符坐标系只告诉你"没有",不告诉你"该有"。这也是纯数据视角需要化学判断兜底的典型场面。
变式。同一套流程换个问题就换一副面孔:做库去重时投影图用来圈"离群分子"(远处孤点常是结构异常或质检漏网);做活性外推评估时(第6.2节的适用域),训练集分布当底图、候选分子当新点,落在底图稀疏区的预测要打问号。特征选择那边也一样:QSAR 建模前的递归消除、 L1 稀疏回归,都是本章方法的直接续篇——工具未变,问题牵引。
主成分化学空间图好用,也容易用出误会,三条纪律保平安。
纪律一,先标准化再投影。描述符量纲差异悬殊(分子量几百,氢键供体数个位数),不做标准化直接投影,第一主成分会被分子量独家绑架——你看到的"化学空间"其实只是分子量坐标轴。标准化之后每个描述符才平等参选。纪律二,散点要带语义着色。纯点位图只回答"分布长什么样",着色才回答"分布意味着什么":按活性着色看性质梯度、按来源着色看库重叠、按骨架着色看多样性——同一张投影图,换一种着色就是换一个问题的答案。纪律三,外推点单独标记。落在训练分布之外的候选(4.3 与 6.2 节的共同关切)在图上用醒目形状标出,让"域外"成为视觉事实而不是统计脚注——这张图因此兼任适用域的沟通工具,向非技术同事解释"为什么这个高分分子我们不送验",指着一个远处的孤点比念十行统计量有效。