第2章:分子描述符基础归纳总结

说实话,我刚入行做QSAR那会儿,最头疼的就是分子描述符。别人跑一个模型,R²能有0.9,我跑出来就0.3。后来才发现,问题出在描述符上——要么选错了,要么没处理好。这一章,我就把这些年积累的分子描述符经验,掰开了揉碎了给你讲讲。

2.1 什么是分子描述符

分子描述符,说白了就是分子的「数字身份证」。它是用数学或计算化学的方法,把分子的结构信息转成一串数字。有了这串数字,计算机才能理解分子,模型才能学出规律。

我习惯把描述符分成这几类:

  • 0D描述符:比如分子量、原子个数。信息量最少,但最稳定。
  • 1D描述符:比如分子式、官能团计数。比0D多点儿信息。
  • 2D描述符:基于分子图论的拓扑指数。比如Wiener指数、Zagreb指数。这类描述符很常用,我项目中80%的模型都靠它。
  • 3D描述符:需要三维构象。像CoMFA、CoMSIA里的立体场和静电场。计算量大,但信息丰富。
  • 4D描述符:考虑构象集合和时间演化。说实话,我一般不用,除非数据量特别大。
我的经验:别一上来就追求复杂描述符。先跑2D描述符,模型不行再往上加。过度设计是新手最常见的毛病。

2.2 描述符的计算与工具

现在工具很多,我主要用这几套:

工具 描述符数量 适用场景 我的评分
RDKit 200+ 日常筛选、预实验 ⭐⭐⭐⭐⭐
PaDEL-Descriptor 1400+ 全面的特征工程 ⭐⭐⭐⭐
Mordred 1800+ 学术研究 ⭐⭐⭐⭐
Dragon 5000+ 工业级应用 ⭐⭐⭐(需付费)

举个例子,用RDKit算描述符很简单:

from rdkit import Chem
from rdkit.Chem import Descriptors

mol = Chem.MolFromSmiles('CCO')  # 乙醇
mw = Descriptors.MolWt(mol)
logp = Descriptors.MolLogP(mol)
hbd = Descriptors.NumHDonors(mol)

print(f"分子量: {mw:.2f}")
print(f"LogP: {logp:.2f}")
print(f"氢键供体数: {hbd}")

输出结果:

分子量: 46.07
LogP: -0.14
氢键供体数: 1

2.3 描述符的筛选策略

算完描述符,你会发现一个问题——太多了。有人算出来几千个描述符,直接扔进模型跑。你想想看,这有多容易过拟合?

我一般按这几步来筛:

  1. 常数筛:方差接近0的描述符,直接扔掉。
  2. 相关性筛:两个描述符相关系数 > 0.95,保留一个。
  3. 重要性排序:用随机森林或LASSO,找top N个。
技巧:我通常保留50-200个描述符。太少欠拟合,太多过拟合。你可以从100个开始调。

做常数筛选时,我习惯这样写:

import pandas as pd
import numpy as np

# 假设 df 是描述符矩阵
def remove_constant_features(df, threshold=0.01):
    variances = df.var()
    to_remove = variances[variances < threshold].index.tolist()
    print(f"移除 {len(to_remove)} 个常数/近常数特征")
    return df.drop(columns=to_remove)
避坑:我曾经踩过一个坑——直接用默认阈值筛选分子量。结果某个系列分子量差别很小,但活性差别很大。后来我改为按数据集动态调整阈值,模型才正常。

2.4 描述符的标准化与缩放

描述符尺度差异很大。分子量几百,logP可能只有几。你不做缩放,模型就会偏向量级大的特征。

我推荐两种方式:

  • Z-score标准化:均值为0,标准差为1。适合有异常值的数据。
  • Min-Max缩放:映射到[0,1]。适合范围固定的描述符(比如是否为芳香环)。

代码实现:

from sklearn.preprocessing import StandardScaler, MinMaxScaler

# Z-score
scaler_z = StandardScaler()
df_z = pd.DataFrame(scaler_z.fit_transform(df), columns=df.columns)

# Min-Max
scaler_mm = MinMaxScaler()
df_mm = pd.DataFrame(scaler_mm.fit_transform(df), columns=df.columns)
关键点:记住,只用训练集的数据去拟合scaler,然后transform训练集和测试集。别把测试集数据混进去,这是泄露。

2.5 常用描述符一览

下面这张表,我做了很多项目才总结出来的:

类别 典型描述符 含义 适用性
物理化学 MolLogP, MolWt, TPSA 脂溶性、分子量、极性表面积 ADME/Tox预测
拓扑 Wiener, Zagreb, BalabanJ 分子连通性、分支度 结构-活性关系
电性 PartialCharge, DipoleMoment 电荷分布、偶极矩 作用机制研究
立体 PMI1, PMI2, PMI3 分子形状的主惯性矩 3D构象分析
指纹 MorganFP, MACCS, AtomPair 子结构存在性 相似性搜索、分类

2.6 本章知识体系

下面这张图,是我做了十多年QSAR总结出来的框架。先看定义,再算工具,然后筛选和缩放,最后应用到模型里。每一步都环环相扣:

分子描述符操作流程 分子结构输入 (SMILES) 描述符计算 (RDKit等) 描述符筛选 (相关性+重要性) 标准化 / 缩放 QSAR模型输入 关键思路 描述符是分子的"特征" 好特征 = 好模型 千万别一次性全扔进模型 避坑提醒 不要用测试集做筛选 不要忘掉标准化 高相关描述符必须去除

2.7 常见问题与避坑指南

这些年下来,我发现很多问题都是共通的。列出来,你碰到类似情况可以直接查:

  • 描述符太多,模型跑不动:先用随机森林的特征重要性排序,砍到100个以内。
  • 模型不收敛:检查一下描述符有没有做标准化。我有个项目就是这样,标准化后收敛速度快了5倍。
  • 训练集和测试集表现差异巨大:大概率是特征泄露了。检查你有没有用全数据做特征筛选。
  • R²很高但预测不准:描述符过多导致过拟合。减少描述符数量,或者加正则化。
重要:我曾经被审稿人指出,训练集和测试集描述符分布不一致。后来我学会了一个检查方法:每次做完描述符,就画个t-SNE图看看分布。分布重叠不好,换个描述符组合。

好了,分子描述符的基础就这些。记住,描述符是QSAR的基石——地基打不好,上面盖多漂亮的模型都白搭。我建议你动手算一组数据,亲自走一遍筛选和缩放的流程。光看不练,三天就忘光了。