REINVENT4(2024)是 REINVENT 系列的重写版本。它的重点不是新算法,而是把研究代码变成可配置、可复现、可扩展的工程化平台——这正是从论文走向生产的关键一步。
四种运行模式
| 模式 | 用途 |
|---|---|
| sampling | 从模型直接采样分子(不优化) |
| scoring | 只对给定分子打分,不生成 |
| transfer learning | 在自己的分子集上微调先验模型 |
| staged learning | 强化学习优化(核心模式) |
scoring 模式常被忽略但很有用:它让你可以先在一批已知分子上测试打分函数,确认它给出的排序符合化学直觉,再拿去做 RL——这能避免用一个有问题的奖励函数跑几天。
四种生成器
# REINVENT4 支持四种分子生成方式
#
# 1) Reinvent(de novo)
# 从零生成完整的 SMILES
# → 探索范围最大,控制最少
#
# 2) LibInvent
# 给定骨架(scaffold),生成 R 基团
# 输入:c1ccc(cc1)[*]
# → 【类库设计的标准场景】
#
# 3) LinkInvent
# 给定两个片段,生成连接子(linker)
# 输入:片段A|片段B
# → 【片段连接与 PROTAC 设计】(见 356)
#
# 4) Mol2Mol
# 给定分子,生成相似的分子
# → 【先导优化的主力】
# 可指定相似性范围(如 Tanimoto 0.5~0.7)
#
# 选择原则:
# 约束越多,生成的分子越可控、越可能有用
# → 【实际项目中 Mol2Mol 和 LibInvent 用得最多】
# → de novo 模式听起来最强,实际最难出可用结果
配置文件结构
# REINVENT4 用 TOML 配置
# config.toml:
run_type = "staged_learning"
device = "cuda:0"
tb_logdir = "tb_logs" # TensorBoard 日志
[parameters]
prior_file = "priors/reinvent.prior"
agent_file = "priors/reinvent.prior"
summary_csv_prefix = "staged_learning"
batch_size = 128
unique_sequences = true
randomize_smiles = true
[learning_strategy]
type = "dap"
sigma = 128 # 【关键参数】
rate = 0.0001
# ---- 多样性过滤(强烈建议开启)----
[diversity_filter]
type = "IdenticalMurckoScaffold"
bucket_size = 25 # 同一骨架最多保留 25 个
minscore = 0.4
minsimilarity = 0.4
# ---- 分阶段学习 ----
[[stage]]
chkpt_file = "stage1.chkpt"
termination = "simple"
max_score = 0.6
min_steps = 100
max_steps = 300
[stage.scoring]
type = "geometric_mean" # 【几何平均:任一项差则总分差】
[[stage.scoring.component]]
[stage.scoring.component.custom_alerts]
[[stage.scoring.component.custom_alerts.endpoint]]
name = "结构警示"
params.smarts = [
"[*;r8]", "[*;r9]", # 8、9 元环
"[#8][#8]", # 过氧化物
"[#7][#7][#7]", # 叠氮类
"[#6](=[#8])[#8][#6](=[#8])", # 酸酐
]
[[stage.scoring.component]]
[stage.scoring.component.MolecularWeight]
[[stage.scoring.component.MolecularWeight.endpoint]]
name = "分子量"
weight = 0.3
transform.type = "double_sigmoid"
transform.high = 500
transform.low = 250
transform.coef_div = 500
transform.coef_si = 20
transform.coef_se = 20
[[stage.scoring.component]]
[stage.scoring.component.QED]
[[stage.scoring.component.QED.endpoint]]
name = "类药性"
weight = 0.3
# ---- 自定义模型打分 ----
[[stage.scoring.component]]
[stage.scoring.component.ExternalProcess]
[[stage.scoring.component.ExternalProcess.endpoint]]
name = "活性预测"
weight = 0.4
params.executable = "python"
params.args = "predict_activity.py"
运行与监控
pip install reinvent4
# 或从源码:git clone https://github.com/MolecularAI/REINVENT4
reinvent -l run.log config.toml
# 输出:
# staged_learning_1.csv 每步生成的分子与各项分数
# stage1.chkpt 检查点
# tb_logs/ TensorBoard 日志
# 【监控要点】:
tensorboard --logdir tb_logs
# 应该关注:
# 1) 平均分数是否上升
# 不上升 = 奖励函数太难或 sigma 太小
#
# 2) 【生成分子的多样性】
# 骨架数是否持续增长?
# → 停滞 = 模式崩溃,需要加强多样性过滤
#
# 3) 各组件分数的变化
# 是否某个组件被牺牲了?
# → 加权求和常见的问题
#
# 4) 【定期人工检查生成的分子】
# 每 100 步导出一批看看
# → 【这一步不能省】
# 分析结果
import pandas as pd
from rdkit import Chem
from rdkit.Chem.Scaffolds import MurckoScaffold
df = pd.read_csv("staged_learning_1.csv")
print(df.columns.tolist())
# 按总分排序,去重
df = df.drop_duplicates(subset=["SMILES"])
top = df.nlargest(200, "Score")
# 统计骨架多样性
top["scaffold"] = top["SMILES"].apply(
lambda s: MurckoScaffold.MurckoScaffoldSmiles(smiles=s))
print(f"前 200 个分子包含 {top['scaffold'].nunique()} 个骨架")
# 【如果骨架数很少,说明多样性不足】
分阶段学习的用法
- 思路:把优化分成多个阶段,每个阶段有不同的目标与终止条件;
- 典型设计:
- 阶段 1:只优化基本性质(分子量、logP、结构警示)——先让模型学会生成合理的分子;
- 阶段 2:加入活性预测,权重逐步提高;
- 阶段 3:加入选择性、可合成性等更严格的约束。
- 为什么有效:一上来就给最难的多目标,模型往往学不动或钻空子;逐步增加难度类似课程学习;
- 检查点复用:每阶段保存 checkpoint,可以从中间阶段分叉尝试不同的后续目标。
工程化的价值
| 改进 | 意义 |
|---|---|
| TOML 配置 | 实验可复现、可版本管理、可 diff |
| 四种生成器统一接口 | 切换场景不必改代码 |
| ExternalProcess 打分 | 可接入任意自有模型 |
| TensorBoard 集成 | 过程可监控 |
| 检查点与分阶段 | 长流程可中断可复用 |
| scoring 独立模式 | 奖励函数可单独验证 |
关键要点
- 先用 scoring 模式验证奖励函数,再跑 RL——避免用有问题的奖励函数浪费几天;
- Mol2Mol 与 LibInvent 在实际项目中最有用;de novo 听起来最强但最难出结果;
- 几何平均聚合适合「必须同时满足」的多目标,加权求和会让差项被补偿;
- 分阶段学习先教会模型生成合理分子,再逐步加难度,比一上来就多目标更有效。
延伸资源
- REINVENT 论文:137《REINVENT 论文精读》;实战:347《用 REINVENT4 生成新分子》;对接约束:351《在分子生成中加入 Docking Score 约束》;
- 分子生成模型:158《AI 分子生成模型》;骨架跃迁:352《Scaffold Hopping 实战》。