MoleculeNet 到底是什么?

说真的,当你真正开始用机器学习做分子性质预测时,第一个问题往往不是什么模型更厉害,而是:数据从哪来?

我自己就踩过这个坑。早年做化学信息学项目时,数据东拼西凑,格式五花八门,光清洗就花了我两周。后来遇到了 MoleculeNet,才算是找到了“组织”。

MoleculeNet 诞生于 DeepChem 项目,由普林斯顿大学团队维护。它不是什么单一数据集,而是一个 数据集集合。说白了,就是一群搞计算化学和机器学习的专家,把散落在各处的分子数据统一收编,还帮你做了标准化处理。

它的目标是啥?就一个:让你能专心搞模型,别再花时间折腾数据格式。

它从哪来?谁在管?

MoleculeNet 的数据来源很广。小到几百个分子的实验测定,大到上千万个分子的虚拟筛选库,都有收录。你可以把它理解成一个数据集的“集市”,每个摊位卖的东西不一样,但包装规格统一。

我个人习惯把它按数据来源分成几类:

  • 实验测量数据:比如从 PubChem、ChEMBL 这些公共数据库里扒下来的实测性质。
  • 计算结果数据:用量子化学、分子动力学算出来的理论值。我记得最开始我还不大信任这类数据,后来发现只要方法靠谱,算出来的比测的还准。
  • 人工标注数据:一些药物化学专家根据经验给出的分类标签,比如“这个分子有毒”。

项目现在由 DeepChem 社区持续维护。版本更新很快,我建议你直接关注 GitHub 上的 deepchem/deepchem 仓库。

核心子数据集一览

MoleculeNet 包含了二十多个子数据集。每个都有不同的任务目标。我把常用的几个列在下面,你以后做项目时可以直接对号入座:

子数据集 任务类型 样本量 预测目标 推荐用途
ESOL 回归 1,128 水溶性(log mol/L) 入门练手
FreeSolv 回归 643 水合自由能(kcal/mol) 评估模型泛化
Lipophilicity 回归 4,200 脂溶性(logD) ADME 预测
BACE 分类 1,513 β-分泌酶抑制活性 药物活性筛选
HIV 分类 41,127 抗 HIV 活性 大规模分类
MUV 分类 93,087 多个靶点活性 虚拟筛选
Tox21 多任务分类 7,831 12种毒性效应 多标签学习
ClinTox 二元分类 1,491 临床毒性 + 失败 安全性预测
我的建议:刚上手时,先拿 ESOL 或 FreeSolv 练手。这两类回归任务数据量小、噪音也相对低。别一上来就碰 HIV 或 MUV,四万多个样本,模型调参能把你折腾死。

常见任务类型

从上面表格就能看出来,MoleculeNet 里的任务主要分两派:

  • 回归任务:预测连续数值。比如溶解度、能垒、结合能。这类问题基本上就是拟合一个函数,用均方误差(MSE)或决定系数(R²)来评估。
  • 分类任务:判定分子有没有某种性质。有毒没毒、活性高低、能不能透过血脑屏障。评估用 ROC-AUC 或 F1 分数比较稳妥。

为什么会这么分类?你想想看,药物研发里,有的是要精确数值('这个分子的logP是多少'),有的只要一个定性判断('这个分子会不会导致肝毒性')。两种任务的处理思路完全不同。

我实际做的过程中就发现,像 logP 这样的回归问题,单纯用分子指纹喂给随机森林就能拿到不错的结果;但到了 hERG 抑制这种分类问题,概率模型几乎一定会预测为中性,你需要从数据配比或者分子图结构上想办法。

一段代码快速上手

下面是我当时用 MoleculeNet 的第一个例子。这段代码会加载 ESOL 数据集,并显示基本的统计信息:

import deepchem as dc
from deepchem.utils import load_simple_data

# 加载 ESOL 数据集
tasks, datasets, transformers = dc.molnet.load_esol()
train_dataset, valid_dataset, test_dataset = datasets

# 看一眼数据长什么样
print(f'任务名: {tasks}')
print(f'训练集样本数: {len(train_dataset)}')
print(f'验证集样本数: {len(valid_dataset)}')
print(f'测试集样本数: {len(test_dataset)}')

# 看看第一条数据
first_mol = train_dataset.X[0]
first_label = train_dataset.y[0]
print(f'第一个分子的 SMILES: {first_mol}')
print(f'对应溶解度 (log mol/L): {first_label}')

嗯,这里要注意一点。MoleculeNet 的返回结构是 (tasks, datasets, transformers),而不是很多人以为的 (X, y)。我第一次用的时候就踩了这个坑,加载之后直接拿 datasets 当 X 用,结果报了一堆类型错误。

MoleculeNet 的独特之处

你可能会问:网上公开的化学数据集那么多,干嘛非得用 MoleculeNet?

我总结了几点:

  1. 统一:所有子数据集都转成了 DeepChem 的 Dataset 对象。不需要你自己写 parser。
  2. 权威:每一个子数据集都来自公认的文献或公共数据库,质量有保障。
  3. 公平比较:它提供了固定的训练/验证/测试划分。你跑出来的结果,可以直接跟别的论文对比。

我印象很深的一件事是,有一次我把自己的模型结果跟某篇顶会论文对比,发现对方划分数据集时用了随机拆分。而我用 MoleculeNet 的官方划分——那个论文的模型直接就过拟合了。所以你想想看,统一的基准有多重要。

一张图看懂体系

下面这张 SVG 图把 MoleculeNet 的整体结构画了出来。你一看就明白了:

MoleculeNet 数据集结构图谱 核心数据来源 PubChem / ChEMBL / 文献 ESOL FreeSolv HIV Tox21 BACE ClinTox MUV 回归任务 分类任务 虚拟筛选 / ADME 预测 统一接口 + 固定划分 = 公平比较
学完这一节,你能回答以下问题:
  • MoleculeNet 数据集集合来自哪里?
  • 你能列出至少 5 个核心子数据集吗?
  • 你清楚回归任务和分类任务的区别吗?
  • 你知道如何用 DeepChem 加载一个 MoleculeNet 子数据集吗?