349

在分子生成中加入 QED 约束

QED 是常用的类药性综合指标。这篇讲清它的构成、作为生成约束的配置方式,以及为什么不该过度依赖它。

QED(Quantitative Estimate of Drug-likeness,Bickerton et al. 2012)把多个理化性质综合成一个 0~1 的分数。它是分子生成中最常用的约束之一,但也是最容易被误用的指标

QED 的构成

它把八个性质各自映射成「期望度函数」,再取加权几何平均:

性质 理想范围(大致)
分子量 MW 约 300
脂水分配系数 ALOGP 约 2~3
氢键供体 HBD
氢键受体 HBA 适中
极性表面积 PSA 适中
可旋转键 ROTB
芳环数 AROM 适中
结构警报 ALERTS

各期望度函数是从已上市口服药物的性质分布拟合出来的。这就决定了它的适用边界:QED 衡量的是「像不像典型的口服小分子药」,而不是「是不是好药」。

计算

from rdkit import Chem
from rdkit.Chem import QED, Descriptors

for smi in [
    "CC(=O)Oc1ccccc1C(=O)O",                                # 阿司匹林
    "COc1cc2ncnc(Nc3ccc(F)c(Cl)c3)c2cc1OCCCN1CCOCC1",       # 吉非替尼类
    "CC(C)Cc1ccc(cc1)C(C)C(=O)O",                           # 布洛芬
]:
    mol = Chem.MolFromSmiles(smi)
    props = QED.properties(mol)
    print(f"QED={QED.qed(mol):.3f}  MW={props.MW:.0f}  "
          f"ALOGP={props.ALOGP:.2f}  PSA={props.PSA:.0f}  "
          f"HBD={props.HBD}  HBA={props.HBA}  ROTB={props.ROTB}")

# 也可自定义权重
print(QED.qed(mol, w=QED.WEIGHT_MAX))     # 各性质权重不同的变体
print(QED.qed(mol, w=QED.WEIGHT_NONE))    # 等权重

在 REINVENT4 中配置

[[stage.scoring.component]]
[stage.scoring.component.QED]
[[stage.scoring.component.QED.endpoint]]
name = "QED"
weight = 0.6
# QED 本身已是 0~1,通常不需要 transform

# 若想强调高 QED,可加 sigmoid
# transform.type = "sigmoid"
# transform.low = 0.4
# transform.high = 0.8
# transform.k = 0.5

为什么不该过度依赖 QED

  • 它是「典型性」而非「优质性」的度量。QED 高只说明这个分子的性质分布接近已上市口服药的中位数。很多成功药物的 QED 并不高——大环化合物、天然产物衍生物、肽类、共价抑制剂、PROTAC 都会得到低 QED,但它们是完全合法的药物模态。
  • 会系统性压制创新:把 QED 权重设得很高,模型会收敛到「平庸的典型小分子」,恰恰排除了新模态的探索空间。
  • 与活性无关:QED 完全不看分子能否结合靶点。一个 QED = 0.95 但毫无活性的分子没有任何价值。
  • 不适用于非口服给药:静脉给药、吸入给药、局部给药的分子,性质要求与口服完全不同。
  • 各性质的权重是经验的:QED 的权重来自对已有药物的拟合,不代表因果关系。

更合理的用法

# 用法一:作为软约束而非主目标
# 权重设低(0.3~0.6),主要目标应该是活性与选择性

# 用法二:只作为下界过滤,不追求最大化
[[stage.scoring.component.QED.endpoint]]
name = "QED_floor"
weight = 0.5
transform.type = "sigmoid"
transform.low = 0.3        # 低于 0.3 惩罚
transform.high = 0.5       # 超过 0.5 就够了,不再加分
transform.k = 1.0
# 这样模型只需保证「不太离谱」,不会为了刷 QED 牺牲其它目标

# 用法三:换成更贴合项目的自定义性质约束
# 与其用 QED 这个综合指标,不如直接约束项目关心的性质:
#   - 中枢神经系统药物 → 用 CNS MPO 而非 QED
#   - 需要口服暴露 → 单独约束 TPSA、HBD、MW
#   - 抗菌药物 → 革兰阴性菌渗透规则与常规类药规则不同

项目特异的 MPO 更有价值

import numpy as np

def desirability(value, low, high, direction="range"):
    """把性质值映射到 0~1,用平滑函数"""
    if direction == "range":
        center, width = (low + high) / 2, max((high - low) / 2, 1e-9)
        return float(np.exp(-((value - center) / width) ** 2))
    if direction == "lower":
        return float(1 / (1 + np.exp((value - high) / (0.1 * abs(high) + 1e-9))))
    return float(1 / (1 + np.exp(-(value - low) / (0.1 * abs(low) + 1e-9))))

def custom_mpo(mol, criteria, weights):
    """按项目需求自定义的多参数评分"""
    scores = []
    for name, (fn, lo, hi, direc) in criteria.items():
        d = desirability(fn(mol), lo, hi, direc)
        scores.append(d ** weights[name])
    return float(np.prod(scores) ** (1 / sum(weights.values())))

# 例:一个针对口服中枢神经系统药物的自定义 MPO
from rdkit.Chem import Descriptors, Crippen
criteria = {
    "MW":    (Descriptors.MolWt,        250, 400, "range"),
    "cLogP": (Crippen.MolLogP,          1.0, 3.5, "range"),
    "TPSA":  (Descriptors.TPSA,          40,  90, "range"),
    "HBD":   (Descriptors.NumHDonors,     0,   2, "lower"),
}
weights = {"MW": 1.0, "cLogP": 1.5, "TPSA": 1.5, "HBD": 1.0}
print(custom_mpo(mol, criteria, weights))

这比 QED 更有价值:QED 是「通用的典型性」,而自定义 MPO 反映的是「你这个项目真正需要什么」。

常见坑与提示

  • QED 衡量「像不像典型口服小分子」,不等于「是不是好药」
  • 权重设太高会压制创新,把模型逼向平庸的典型分子;
  • 用作下界过滤(超过 0.5 不再加分)比追求最大化更合理
  • 项目特异的自定义 MPO 通常比通用 QED 更有指导价值。

延伸资源