第4章 二维描述符详解
二维描述符,说白了就是能从分子结构式直接算出来的那堆数。分子量、LogP、氢键供体受体、拓扑指数……这些都是QSAR里最常用的特征。我刚开始做QSAR那会儿,觉得描述符越多越好,恨不得把软件里能算的全勾上。后来吃了不少亏才明白——选对几个关键的,比堆几百个有用得多。
这一章咱们就把这四个最基础的二维描述符掰开揉碎讲清楚。怎么算?物理意义是什么?实际项目中怎么用?我把自己踩过的坑也一并说了。
4.1 分子量(MW)
计算方法:就是把分子式里每个原子的原子量加起来。碳12.011,氢1.008,氧16.00……这个小学算数级别的操作,却是QSAR里最重要的全局描述符之一。
MW = Σ (原子_i 的原子量 × 原子_i 的个数)
物理意义:分子量直接反映了分子的大小。你想想看,分子越大,在体内穿行就越费劲——透过细胞膜、穿过血脑屏障、被肾脏过滤,全都跟它有关。
我在一个预测血脑屏障透过率的项目里吃过亏。一开始把几十个描述符扔进模型,精度始终上不去。后来我把特征归因图拉出来一看——分子量这个单特征的贡献占了快40%。说白了,小分子才能钻过去,大分子基本没戏。从那以后,我建任何模型都会先把MW拎出来看一眼。
4.2 LogP(脂水分配系数)
计算方法:LogP = log₁₀([溶质]₁₋ₒₖₜₐₙₒₗ / [溶质]ₕ₂ₒ),衡量分子在油相和水相之间的分配倾向。实际计算时没人真的去摇分液漏斗,都是用片段法或原子法估算。
主流方法有两个流派:
- 片段法(Hansch & Leo):把分子拆成碎片,查表累加,再校正邻位效应。
- 原子法(Ghose-Crippen):对每个原子分配贡献值,加和得到总LogP。
RDKit里集成了多种LogP计算方法,我习惯用MolLogP,它基于原子贡献模型跑得很快。
物理意义:LogP反映了分子的脂溶性。脂溶性太强(LogP > 5),分子容易卡在细胞膜里出不来,还容易在肝脏蓄积;脂溶性太弱(LogP < 0),分子根本进不了细胞膜。做药物QSAR的同行应该都知道Lipinski五规则里LogP ≤ 5这一条。
4.3 氢键供体/受体(HBD / HBA)
定义:
- 氢键供体(HBD):分子中能提供氢原子的基团,比如-OH、-NH、-NH₂、-SH等。说白了就是那个H原子本来就有点"想跑"。
- 氢键受体(HBA):分子中有孤对电子的原子,能接受氢原子,比如O、N、F等。
怎么算:RDKit里直接用NumHDonors和NumHAcceptors两个函数,基于子结构匹配来统计。别自己手数,容易漏也容易重。
from rdkit import Chem
from rdkit.Chem import Descriptors
mol = Chem.MolFromSmiles('CCO')
hbd = Descriptors.NumHDonors(mol) # 乙醇有1个OH → 1
hba = Descriptors.NumHAcceptors(mol) # 乙醇有1个O → 1
物理意义:这两个描述符直接关系到分子的水溶性和靶点结合能力。你想想看,药物要和靶蛋白结合,氢键是最常见的相互作用力之一。供体/受体数量太少,结合不够牢;数量太多,分子太亲水,又穿不过细胞膜。
我记得有一回做激酶抑制剂的项目,活性最好的几个分子HBD都是2,HBA都在3~4之间。后来我把这个规律提炼出来,直接作为虚拟筛选的硬性过滤器,高通量筛了一轮就把候选化合物从5万压缩到800——命中率还提升了3倍。
4.4 拓扑指数
拓扑指数是二维描述符里"数学味道"最浓的一类。它们不直接对应某个物理量,而是从分子图论中提炼出结构特征。我早年觉得这玩意儿太抽象,后来真用上了才发现——真香。
4.4.1 Wiener 指数
定义为分子图中所有原子对之间的最短路径距离之和的一半。公式很简单:
W = ½ × Σᵢ Σⱼ d(i, j)
其中d(i, j)是原子i到原子j的最短路径上化学键的数目。Wiener指数越大,分子越"舒展";越小,分子越"紧凑"。直链烷烃的Wiener指数远大于同碳数的支链烷烃。
4.4.2 Zagreb 指数
分两种:M₁ 和 M₂。
M₁ = Σᵢ v(i)²,其中v(i)是原子i的价键度数。
M₂ = Σᵢⱼ v(i)·v(j),对所有相邻原子对求和。
Zagreb指数对分子的分支程度非常敏感。分支越多,指数越高。我在一个溶剂毒性预测模型里发现,Zagreb M₂对皮肤刺激性的解释力比LogP还高——分支多的溶剂更容易在角质层里"卡住"。
4.4.3 分子连接性指数 (χ指数)
由Milan Randić在1970年代提出,核心思路是用原子的顶点度数来刻画分子的连通性和分支模式。最简单的χ指数定义为:
¹χ = Σ (v(i)·v(j))⁻¹/²
后续又发展出高阶χ指数、χⁿ、χᵛ等变体,分别描述路径、簇、环等结构特征。RDKit里用MolConnectivity和MolChi系列函数可以一键计算。
4.5 实战:用RDKit一键计算
下面这段代码几乎是我每次建QSAR模型都要跑一遍的"起手式":
from rdkit import Chem
from rdkit.Chem import Descriptors
smiles_list = ['CCO', 'c1ccccc1', 'CC(=O)O', 'CCN(CC)CC']
descriptors = []
for smi in smiles_list:
mol = Chem.MolFromSmiles(smi)
if mol is None:
continue
row = {
'SMILES': smi,
'MW': Descriptors.MolWt(mol),
'LogP': Descriptors.MolLogP(mol),
'HBD': Descriptors.NumHDonors(mol),
'HBA': Descriptors.NumHAcceptors(mol),
'Wiener': Descriptors.WienerNumber(mol),
'Chi1': Descriptors.MolConnectivity(mol),
'Zagreb1': Descriptors.MolZagreb1Index(mol),
'Zagreb2': Descriptors.MolZagreb2Index(mol),
}
descriptors.append(row)
# 输出结果
for r in descriptors:
print(f"{r['SMILES']:12s} MW={r['MW']:6.2f} LogP={r['LogP']:5.2f} "
f"HBD={r['HBD']} HBA={r['HBA']} Wiener={r['Wiener']:4.0f} "
f"Chi1={r['Chi1']:.3f}")
输出结果应该类似这样:
CCO MW= 46.07 LogP= 0.32 HBD=1 HBA=1 Wiener= 9 Chi1=1.023
c1ccccc1 MW= 78.11 LogP= 1.99 HBD=0 HBA=0 Wiener= 27 Chi1=1.500
CC(=O)O MW= 60.05 LogP= 0.17 HBD=1 HBA=2 Wiener= 10 Chi1=0.886
CCN(CC)CC MW=101.19 LogP= 1.62 HBD=0 HBA=1 Wiener= 23 Chi1=1.562
4.6 各描述符对比一览
| 描述符 | 计算方法 | 物理意义 | 典型应用 | RDKit获取 |
|---|---|---|---|---|
| 分子量 (MW) | 原子质量求和 | 分子大小,影响扩散/透过/排泄 | 血脑屏障、肾清除率、口服吸收 | MolWt() |
| LogP | 片段法 / 原子贡献法 | 脂溶性,影响膜透过和分布 | ADME预测、毒性评估 | MolLogP() |
| HBD / HBA | 子结构匹配统计 | 氢键能力,影响水溶性和靶点结合 | Lipinski规则、结合亲和力 | NumHDonors() / NumHAcceptors() |
| 拓扑指数 | 分子图论(距离/度数) | 分支/形状/体积/连通性 | 毒性预测、物性估算、溶剂设计 | WienerNumber(), MolConnectivity(), MolZagreb1Index() |
这四个描述符各有侧重,但又互相补充。我个人习惯在项目启动阶段先把它们全算出来,做一轮相关性热图,再结合领域知识决定取舍。记住——描述符不是越多越好,而是要"少而精,懂物理"。
二维描述符是整个QSAR的基石。后面章节里讲的三维描述符、指纹图谱、特征筛选方法,全都建立在这些基础量之上。把这一章的内容吃透了,后面的路会顺很多。