136

MOSES 论文精读:分布学习基准能回答什么,不能回答什么

MOSES 专注分布学习评测。这篇讲清它的指标体系、与 GuacaMol 的分工,以及分布指标的根本局限。

MOSES(Molecular Sets,Polykovskiy 等,2020)与 GuacaMol 互补:GuacaMol 侧重目标导向优化,MOSES 侧重分布学习。它提供了统一的数据集、基线模型实现与一套细致的分布指标。

MOSES 提供什么

组成 内容
标准数据集 从 ZINC Clean Leads 筛选的约 190 万分子
固定划分 训练/测试/骨架测试三部分
基线实现 字符 RNN、VAE、AAE、JT-VAE、LatentGAN 等
评价指标 十余个分布与质量指标

「骨架测试集」是 MOSES 的一个重要设计:它包含训练集中完全没有出现过的骨架,用于检验模型是否只是在记忆而非学习化学规律。

指标体系

# 基础指标
#   Valid       有效 SMILES 比例
#   Unique@1k   前 1000 个中唯一的比例
#   Unique@10k  前 10000 个中唯一的比例
#   Novelty     不在训练集中的比例
#
# 分布相似性指标(都是与参考集比较)
#   FCD         Fréchet ChemNet Distance —— 综合性最强
#   SNN         最近邻相似度:生成分子与参考集最相似分子的平均相似度
#   Frag        片段相似度:BRICS 片段的分布差异
#   Scaf        骨架相似度:Bemis-Murcko 骨架的分布差异
#
# 性质分布(Wasserstein 距离)
#   logP、SA(可合成性)、QED(类药性)、MW
#
# IntDiv(内部多样性)
#   生成集合内部的平均不相似度
#   → 【检测模式崩溃的关键指标】
#
# Filters
#   通过 MCF + PAINS 等过滤器的比例
#
# 【指标之间的张力】:
#   Novelty 高 vs FCD 低(像训练集)—— 天然冲突
#   IntDiv 高 vs 性质分布匹配 —— 也有冲突
#   → 【不存在所有指标都最优的模型】
#   → 单看一个指标排名毫无意义

使用

pip install molsets

import moses

# 加载标准数据集
train = moses.get_dataset("train")       # 约 160 万
test = moses.get_dataset("test")
test_scaffolds = moses.get_dataset("test_scaffolds")

# 评价生成的分子
generated = my_model.sample(30000)       # 建议至少 3 万个
metrics = moses.get_all_metrics(
    gen=generated,
    n_jobs=8,
    device="cuda",
    test=test,
    test_scaffolds=test_scaffolds,
)

for k, v in sorted(metrics.items()):
    print(f"{k:20s} {v:.4f}")

# 输出示例:
#   valid                0.9750
#   unique@1000          1.0000
#   unique@10000         0.9990
#   FCD/Test             0.4120     ← 越小越好
#   SNN/Test             0.5850
#   Frag/Test            0.9980     ← 越大越好
#   Scaf/Test            0.8500
#   FCD/TestSF           1.2300     ← 骨架测试集,通常明显更差
#   Scaf/TestSF          0.1200     ← 【这个指标最能说明泛化能力】
#   IntDiv               0.8560
#   Filters              0.9700
#   Novelty              0.8900

# 【判读要点】:
#   Scaf/TestSF 低 = 模型无法生成新骨架
#              → 只是在重排训练集的结构
#   IntDiv 低   = 模式崩溃,生成的分子高度相似
#   Filters 低  = 生成了很多有问题的结构

模式崩溃:最需要警惕的失效

# 模式崩溃(mode collapse):
#   模型只学会生成分布中的一小部分
#   → 生成的分子看起来都差不多
#
# 为什么危险:
#   Valid、Unique、Novelty 都可能很高,
#   但生成的都是同一类分子的微小变体
#   → 【对药物发现毫无价值】
#
# 检测方法:
#   1) IntDiv(内部多样性)
#      MOSES 直接提供
#      IntDiv < 0.8 需要警惕
#
#   2) 骨架计数
#      生成 10000 个分子,有多少个不同的
#      Bemis-Murcko 骨架?
#      → 比例太低说明多样性不足
#
#   3) 化学空间可视化
#      用 UMAP/t-SNE 把生成分子与参考集
#      投影到同一空间(见 052)
#      → 直观看出是否只覆盖了一小块区域
#
#   4) 性质分布的方差
#      不只看均值是否匹配,还要看分布宽度

from rdkit import Chem
from rdkit.Chem.Scaffolds import MurckoScaffold

def scaffold_diversity(smiles_list):
    scafs = set()
    valid = 0
    for smi in smiles_list:
        mol = Chem.MolFromSmiles(smi)
        if mol is None:
            continue
        valid += 1
        scafs.add(MurckoScaffold.MurckoScaffoldSmiles(mol=mol))
    return {
        "n_valid": valid,
        "n_scaffolds": len(scafs),
        "scaffold_ratio": len(scafs) / max(valid, 1),
    }
# scaffold_ratio < 0.1 通常说明多样性严重不足

MOSES 与 GuacaMol 的分工

MOSES GuacaMol
侧重 分布学习 目标导向优化
回答的问题 模型学到了化学空间吗 模型能优化目标吗
基线实现 提供多个完整实现 较少
骨架泛化测试 有(TestSF) 部分任务涉及
易被刷分 中等 严重(见 135《GuacaMol 论文精读》

建议两者都跑:MOSES 回答「模型是否学到了合理的化学」,GuacaMol 回答「模型能否朝目标优化」。但两者都不回答「生成的分子有没有用」。

分布指标的根本局限

  • 「像训练集」与「有价值」是两回事这是最根本的问题。药物发现要的是训练集里没有的好分子,而分布指标奖励的恰恰是相似性;
  • 指标之间存在内在冲突:不可能同时最大化新颖性与分布匹配度——因此「在所有指标上都好」的模型不存在,看排行榜要看权衡
  • 不考虑目标靶点:分布学习完全不知道你要打什么靶点;
  • 不考虑可合成性的真实难度:SA score 只是粗糙的估计(见 135《GuacaMol 论文精读》);
  • 实际项目中的生成任务几乎总是有约束的:给定骨架做修饰、给定口袋做设计、多参数同时满足——纯分布学习的设定与实际需求差距很大

关键要点

  • Scaf/TestSF 指标最能说明泛化能力——低值意味着模型只在重排训练集结构;
  • IntDiv 是检测模式崩溃的关键,而模式崩溃时其它指标可能都很好看;
  • 指标之间存在内在冲突,不存在全面最优的模型,看排行榜要看权衡;
  • 分布指标奖励「像训练集」,而药物发现要的是「训练集里没有的好分子」。

延伸资源