220

DeepChem MolNet Loaders:标准数据集加载方法

DeepChem 的 MolNet loader 一行加载标准分子数据集与划分,是建立可比实验的便捷入口。这篇给出参数含义、返回值结构与常见误用。

DeepChem MolNet Loadersdc.molnet.load_* 这一族函数,把「下载数据 → 解析 SMILES → 特征化 → 划分 → 归一化」这一整套预处理压缩成一次调用。做基线实验和方法对比时,它能省掉大量重复劳动,但默认行为里藏着几个必须知道的细节

基本调用

import deepchem as dc

tasks, datasets, transformers = dc.molnet.load_delaney(
    featurizer="ECFP",        # 特征化方式
    splitter="scaffold",      # 划分方式
    reload=True,              # 复用本地缓存
)
train, valid, test = datasets
print(tasks)                  # ['measured log solubility in mols per litre']
print(train.X.shape, train.y.shape, train.w.shape, train.ids[:2])

返回的三元组结构固定:tasks(任务名列表)、datasets(训练/验证/测试三元组)、transformers(做过的变换列表,评测时必须传回去)。

Dataset 的四个字段

字段 含义
X 特征矩阵
y 标签
w 样本权重,多任务里缺失标签处为 0
ids 分子标识(通常是 SMILES)

w 这一列容易被忽略:多任务数据集里大量标签是缺失的,权重为 0 表示该样本在该任务上不计入损失。自己写训练循环时如果不用 w,就会把缺失值当成真实标签学进去。

特征化与划分选项

# 常用 featurizer
"ECFP"        # 圆形指纹,快,强基线
"GraphConv"   # 图卷积用的分子图
"Weave"       # Weave 模型专用
"smiles2img"  # 分子图像
"Raw"         # 原始 RDKit Mol,自己后续处理

# 常用 splitter
"random"      # 只用于 sanity check
"scaffold"    # Bemis-Murcko 骨架划分,默认应该用这个
"butina"      # 基于相似性聚类划分
"stratified"  # 分层,适合不平衡分类
"task"        # 按任务划分

三个常见误用

  • 评测忘了传 transformers。多数回归数据集默认做了 NormalizationTransformer,即把 y 标准化。评测时不传回 transformers,得到的 RMSE 是标准化尺度上的值,看起来好得离谱且无法与文献比较:
    metric = dc.metrics.Metric(dc.metrics.rms_score)
    print(model.evaluate(test, [metric], transformers))   # 正确
    print(model.evaluate(test, [metric]))                 # 错误,尺度不对
    
  • random 划分报结果。随机划分下同骨架类似物会跨越训练与测试集,指标虚高且区分度极低。默认就用 scaffold,随机划分只当上界参考。
  • 只跑一个种子。多数 MolNet 数据集只有一两千个分子,不同划分种子间波动很大。应循环多个 seed 报均值与标准差:
    scores = []
    for seed in range(5):
        _, (tr, va, te), trans = dc.molnet.load_bbbp(
            featurizer="ECFP", splitter="scaffold", seed=seed)
        # 训练并评测,收集分数
    

缓存与自定义数据

# 缓存位置
import os
os.environ["DEEPCHEM_DATA_DIR"] = "/data/deepchem"

# 用同样的流水线处理自己的 CSV
featurizer = dc.feat.CircularFingerprint(size=2048, radius=2)
loader = dc.data.CSVLoader(tasks=["activity"], feature_field="smiles",
                           featurizer=featurizer)
dataset = loader.create_dataset("my_data.csv")

splitter = dc.splits.ScaffoldSplitter()
train, valid, test = splitter.train_valid_test_split(dataset)

这才是 loader 体系真正的长期价值:把公开数据集上验证过的预处理流程,原样套用到自己的数据上,保证内外实验口径一致。

上手提示

  • 返回的 transformers 必须在评测时传回,否则指标尺度不对;
  • 多任务数据集要用 w 权重处理缺失标签;
  • 默认用 scaffold 划分,并跑多个 seed 报均值 ± 标准差;
  • 把同一套 loader 流程套用到自家 CSV,保证内外口径一致。

延伸资源