390

合成可及性再讨论:SA Score、SCScore 与 RAScore 怎么选

SA Score、SCScore 与 RAScore 衡量合成难度的方式不同。这篇对比三者的原理、适用场景与选择建议。

「这个分子好不好合成」有多种量化方式,各自的原理与含义不同。选错指标会导致系统性的偏差——比如惩罚了本来容易合成的新颖结构。

三个指标的原理对比

SA Score SCScore RAScore
提出 2009 2018 2021
原理 片段频率 + 复杂度惩罚 从反应数据学「产物比反应物复杂」 用逆合成求解结果训练的分类器
训练数据 PubChem 片段统计 Reaxys 反应对 ChEMBL + AiZynthFinder 求解结果
输出 1(易)~10(难) 1(简单)~5(复杂) 0~1 的可解概率
速度 极快
直接对应 「片段常见程度」 「合成复杂度」 「能否找到路线」

SA Score:最快但最粗

from rdkit import Chem, RDConfig
import sys, os
sys.path.append(os.path.join(RDConfig.RDContribDir, "SA_Score"))
import sascorer

mol = Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O")
print(f"SA Score: {sascorer.calculateScore(mol):.2f}")
  • 原理:分子中的片段在 PubChem 中越常见,分数越低(越易合成);再加上手性中心、螺环、桥环、大环、尺寸的复杂度惩罚。
  • 优点:毫秒级,可用于生成模型的每一步打分;
  • 关键缺陷它衡量的是「片段常见程度」而非「合成可行性」。一个用常规反应就能做出来、但骨架少见的分子,SA Score 会偏高——这系统性地惩罚了新颖性

SCScore:基于反应数据的复杂度

# 从 ASKCOS 或独立仓库获取
# 训练思路:在 Reaxys 反应中,产物通常比反应物「更复杂」
#          用这个偏序关系训练一个神经网络打分器

from scscore.standalone_model_numpy import SCScorer

model = SCScorer()
model.restore()
smi = "CC(=O)Oc1ccccc1C(=O)O"
print(f"SCScore: {model.get_score_from_smi(smi)[1]:.3f}")
  • 优点:基于真实反应数据,比片段频率更贴近合成逻辑;能反映「构建这个分子需要多少合成努力」。
  • 局限:仍不考虑起始原料可得性;训练目标是相对复杂度而非绝对可合成性。

RAScore:直接预测「能否找到路线」

pip install rascore

from RAScore import RAScore_XGB

scorer = RAScore_XGB.RAScorerXGB()
smi = "CC(=O)Oc1ccccc1C(=O)O"
print(f"RAScore: {scorer.predict(smi):.3f}")     # 0~1
  • 原理:用 AiZynthFinder 对大量 ChEMBL 分子跑逆合成,把「能否找到完整路线」作为标签训练分类器。它是逆合成结果的快速代理。
  • 优点:直接对应实际关心的问题(能否合成);速度快,可用于大规模筛选;
  • 局限:继承了 AiZynthFinder 的偏差(模板库覆盖、库存定义);训练数据是 ChEMBL 分子,对差异很大的化学空间外推能力有限。

三者的相关性与差异

import pandas as pd
import numpy as np

# 对同一批分子算三个分数,看它们的一致性
df = pd.DataFrame({
    "smiles": smiles_list,
    "sa": [sascorer.calculateScore(Chem.MolFromSmiles(s)) for s in smiles_list],
    "sc": [scscorer.get_score_from_smi(s)[1] for s in smiles_list],
    "ra": [rascorer.predict(s) for s in smiles_list],
})

print(df[["sa", "sc", "ra"]].corr(method="spearman"))

# 典型观察:
#   三者的相关性中等(Spearman 常在 0.5~0.7)
#   → 它们衡量的确实是不同的东西
#
# 分歧最有信息量的情况:
#   SA 高但 RA 高(片段少见但能找到路线)
#     → 新颖但可合成的结构,SA Score 误判了
#   SA 低但 RA 低(片段常见但找不到路线)
#     → 可能是起始原料不可得或需要特殊反应

选择建议

场景 推荐 理由
生成模型的每步打分 SA Score 只有它足够快
生成后的批量初筛 RAScore 直接对应可合成性
候选精选(top 100) 实际跑逆合成 最可靠
比较分子的合成复杂度 SCScore 基于反应数据
最终决策 合成化学家评审 不可替代

分级使用的实际流程

# 生成阶段(每步都算,需要毫秒级)
#   → SA Score,用平滑 transform 而非硬阈值

# 生成后初筛(几千个分子)
#   → RAScore > 0.5 作为过滤

# 候选评估(几百个)
#   → AiZynthFinder 实际跑逆合成(见 385)
#     看 is_solved 与 n_steps

# 最终确认(几十个)
#   → 合成化学家评审路线可行性与成本
#   → 这一步的通过率是所有前面步骤质量的真实检验

# 记录反馈:
#   把化学家的判断与各分数对比,
#   校准哪个分数在自家化学空间上最可靠

用自家数据校准

# 通用阈值不一定适合你的团队
import numpy as np

# 拿公司历史上真正合成过的分子算分数分布
historical = [sascorer.calculateScore(Chem.MolFromSmiles(s))
              for s in synthesized_compounds]

print(f"历史合成分子 SA 分布:")
print(f"  中位数  {np.median(historical):.2f}")
print(f"  90 分位 {np.percentile(historical, 90):.2f}")

# 用 90 分位作为阈值,比照搬通用的 6.0 更贴合实际
# 不同公司的合成能力不同,阈值也应不同

# 更好的做法:
#   收集「设计了但最终没做出来」的分子,
#   看它们的分数分布 —— 这是真正的负样本

关键要点

  • SA Score 衡量片段常见程度,会系统性惩罚新颖但易合成的结构
  • RAScore 直接预测「能否找到路线」,最贴近实际关心的问题;
  • 三者相关性只有中等,分歧之处最有信息量;
  • 用自家历史合成分子校准阈值,比照搬通用值合理得多。

延伸资源