化合物优先级排序的本质是多参数优化(MPO):把活性、选择性、溶解度、代谢稳定性、安全性等多个指标综合成一个可比较的判断。做得好能显著提高决策质量,做得差则会系统性地误导团队。
为什么不能用硬阈值
# 传统做法:设一组硬阈值,全部满足的才保留
#
# MW < 500 且 logP < 5 且 溶解度 > 50 μM 且 hERG > 10 μM
#
# 三个根本问题:
#
# 1) 阈值附近的悬崖
# logP = 5.01 被淘汰、5.00 被保留
# 而预测/测量误差远大于 0.01 —— 这个切分毫无道理
#
# 2) 忽略了「差多少」
# 溶解度 49 μM 和 5 μM 都算「不达标」,但差别巨大
#
# 3) 无法权衡
# 一个活性极好但溶解度略低的分子,
# 与一个各项平庸但都达标的分子,哪个更值得做?
# 硬阈值给不出答案
#
# MPO 的解法:把每个指标映射到连续的「期望度」,再综合
期望度函数
import numpy as np
def desirability_higher(v, low, high):
"""越大越好:low 以下接近 0,high 以上接近 1"""
if v is None or np.isnan(v):
return 0.5
k = max((high - low) / 6, 1e-9)
return float(1 / (1 + np.exp(-(v - (low + high) / 2) / k)))
def desirability_lower(v, low, high):
"""越小越好"""
if v is None or np.isnan(v):
return 0.5
k = max((high - low) / 6, 1e-9)
return float(1 / (1 + np.exp((v - (low + high) / 2) / k)))
def desirability_range(v, low, high):
"""落在区间内最好(如 logD)"""
if v is None or np.isnan(v):
return 0.5
center, width = (low + high) / 2, max((high - low) / 2, 1e-9)
return float(np.exp(-((v - center) / width) ** 2))
# 关键设计选择:
# 1) 用平滑函数而非阶跃 → 消除阈值悬崖
# 2) 缺失值给 0.5(中性)而非 0 → 避免因缺数据被误杀
# 3) 上下限从 TPP 反推(见 414),而非拍脑袋
综合:几何平均而非算术平均
def mpo_score(compound, criteria):
"""criteria: {name: (fn, low, high, weight)}"""
scores, weights = [], []
for name, (fn, low, high, w) in criteria.items():
d = fn(compound.get(name), low, high)
scores.append(max(d, 1e-6) ** w)
weights.append(w)
return float(np.prod(scores) ** (1 / sum(weights)))
CRITERIA = {
"pIC50": (desirability_higher, 7.0, 9.0, 2.0),
"selectivity": (desirability_higher, 1.0, 2.0, 1.5),
"logD": (desirability_range, 1.0, 3.5, 1.0),
"solubility": (desirability_higher, 10, 100, 1.5),
"HLM_CLint": (desirability_lower, 10, 50, 1.5),
"hERG_pIC50": (desirability_lower, 4.5, 5.5, 1.5),
"Papp": (desirability_higher, 2, 10, 1.0),
}
# 为什么用几何平均:
# 算术平均:一个 0 分项可被其它高分项掩盖
# (0 + 1 + 1 + 1) / 4 = 0.75 ← 看着还行,但有致命缺陷
# 几何平均:任一项接近 0 则整体接近 0
# (0 × 1 × 1 × 1)^(1/4) = 0 ← 正确反映「有致命缺陷」
#
# 这更符合「每一项都必须过关」的实际要求
不确定性感知
def mpo_with_uncertainty(predictions, uncertainties, criteria, n_sim=2000):
"""蒙特卡洛传播预测不确定性"""
scores = []
for _ in range(n_sim):
sampled = {}
for k, v in predictions.items():
sd = uncertainties.get(k, 0.0)
sampled[k] = np.random.normal(v, sd) if sd > 0 else v
scores.append(mpo_score(sampled, criteria))
scores = np.array(scores)
return {
"mean": float(scores.mean()),
"std": float(scores.std()),
"ci_90": [float(np.percentile(scores, 5)),
float(np.percentile(scores, 95))],
}
def is_significantly_better(res_a, res_b, overlap_threshold=0.3):
"""判断 A 是否显著优于 B"""
a_lo, a_hi = res_a["ci_90"]
b_lo, b_hi = res_b["ci_90"]
overlap = max(0, min(a_hi, b_hi) - max(a_lo, b_lo))
span = max(a_hi - a_lo, b_hi - b_lo, 1e-9)
return (res_a["mean"] > res_b["mean"]) and (overlap / span < overlap_threshold)
# 最重要的产出不是排名,而是:
# 「哪些化合物之间的差异在统计上不显著」
#
# 如果 A 和 B 的置信区间高度重叠,
# 就不该仅凭 MPO 分数选 A 弃 B ——
# 此时应引入其它因素:合成难度、新颖性、专利空间、化学多样性
权重怎么定
- 从 TPP 反推(见 414《目标产品特征 TPP》):TPP 要求口服每日一次,那么代谢稳定性的权重就应该高;
- 按项目阶段调整:早期活性权重高,后期性质权重上升;
- 按当前瓶颈调整:如果所有分子都卡在溶解度上,就提高溶解度的权重,引导优化方向;
- 做敏感性分析:改变权重,看排名是否稳定。如果排名对权重极其敏感,说明候选之间的差异本来就不明显;
- 让跨职能团队共同确定:权重反映的是价值判断,不应由单一角色决定。
完整的排序流程
import pandas as pd
def rank_compounds(df, criteria, uncertainty_cols=None):
results = []
for _, row in df.iterrows():
preds = {k: row.get(k) for k in criteria}
uncs = ({k: row.get(f"{k}_std", 0) for k in criteria}
if uncertainty_cols else {})
r = (mpo_with_uncertainty(preds, uncs, criteria)
if uncs else {"mean": mpo_score(preds, criteria),
"ci_90": [None, None]})
results.append({"id": row["id"], "smiles": row["smiles"],
"mpo": r["mean"], "ci_low": r["ci_90"][0],
"ci_high": r["ci_90"][1]})
out = pd.DataFrame(results).sort_values("mpo", ascending=False)
# 关键补充:标出哪些与第一名无显著差异
if out["ci_low"].notna().all():
top = out.iloc[0]
out["tied_with_top"] = out.apply(
lambda r: not (top["ci_low"] > r["ci_high"]), axis=1)
return out
# 最终选择时,在「与第一名无显著差异」的分子中,
# 按化学多样性、合成难度、新颖性等因素挑选
# → 这比死板地取 top N 合理得多
常见误区
- 把 MPO 分数当作绝对判断:它是排序工具,不是「这个分子有多好」的度量;
- 忽略预测不确定性:用预测值做 MPO 而不考虑误差,会给出虚假的精确排名;
- 权重拍脑袋定:应从 TPP 反推并做敏感性分析;
- 只取 top N:应该在「统计上无显著差异」的集合中考虑多样性;
- 用算术平均:会掩盖致命缺陷;
- 不区分预测值与实测值:两者的可信度完全不同,应分别处理或在不确定性中体现。
关键要点
- 用平滑期望度函数替代硬阈值,消除阈值悬崖;
- 用几何平均而非算术平均,防止致命缺陷被高分项掩盖;
- 最有价值的产出是「哪些化合物差异不显著」,而非精确排名;
- 权重应从 TPP 反推,并做敏感性分析验证排名稳定性。
延伸资源
- TPP:414《目标产品特征 TPP》;先导优化:405《Lead Optimization》;
- 不确定性与决策:416《决策中的概率思维》、417《计算与实验的差距》。