deepchem教程–使用分裂器
在使用机器学习时,通常会将数据分为训练集、验证集和测试集。MoleculeNet加载器自动完成这一操作。但是应该如何划分数据呢?这个问题乍一看很简单,但结果却相当复杂。拆分数据的方法有很多,选择哪一种方法会对结果的可靠性产生很大影响。本教程介绍DeepChem提供的一些拆分方法。
本教程和本序列中的其余内容可以在谷歌colab中完成。如果你想在colab中打开这个笔记本,你可以使用下面的链接。
Colab
!pip install --pre deepchem
import deepchem
deepchem.__version__
Splitters
在DeepChem中,将样本分割到多个数据集的方法由“Splitter”对象定义。为数据选择合适的方法是非常重要的。否则,你训练过的模型可能看起来比实际情况要好得多。
考虑一个典型的药物开发管道。你可以从筛选成千上万的分子开始,看看它们是否与你感兴趣的目标结合。一旦你找到一个似乎有效的方法,你就试着通过测试它的数千个小变种来优化它,寻找一个结合更强的方法。然后你可能会在动物身上进行测试,发现它具有不可接受的毒性,所以你会尝试更多的变化来解决问题。
这对化学数据集有一个重要的后果:它们通常包括许多彼此非常相似的分子。如果以简单的方式将数据分成训练集和测试集,训练集将包括许多与测试集中的分子非常相似的分子,即使它们并不完全相同。因此,该模型可能在测试集上表现得非常好,但当你试图将其用于与训练数据不太相似的其他数据时,就会严重失败。
让我们来看看在DeepChem中发现的一些分裂器。
RandomSplitter
这是最简单的分配器之一。它只是以完全随机的方式为训练、验证和测试集选择样本。
我们不是刚说过这不是个好主意吗?这取决于你的数据。如果每个样本都真正独立于其他样本,那么这是一种分割数据的好方法。拆分器没有普遍的最佳选择。这完全取决于您的特定数据集,对于某些数据集,这是一个很好的选择。
RandomStratifiedSplitter
一些数据集非常不平衡:所有样本中只有很小一部分是阳性的。在这种情况下,随机拆分有时可能导致某些任务的验证或测试集只有很少甚至没有积极样本。这使得它无法评估业绩。
Randomstratifiedsplitter
通过均匀地将正面和负样本划分来解决这一点。如果您要求进行80/10/10拆分,则验证和测试集将不仅包含10%的样本,还包含每个任务的10%正样本。
ScaffoldSplitter
这个分裂器试图解决上面讨论的许多分子彼此非常相似的问题。它确定了构成每个分子核心的支架,并确保具有相同支架的所有分子都被放入相同的数据集中。这仍然不是一个完美的解决方案,因为两个分子可能有不同的支架,但在其他方面非常相似,但它通常比随机分裂有很大的改进。
ButinaSplitter
这是另一个试图解决相似分子问题的分离器。它会根据他们的分子指纹对他们进行分组,这样指纹相似的人就会倾向于在同一个数据集中。这种分裂算法所需的时间是分子数量的平方,因此它主要适用于中小型数据集。
这个拆分器把一切都留给了用户。你告诉它在每个数据集中放入哪些样本。当您事先知道特定的分割适合您的数据时,这是非常有用的。
一个例子是时间分裂。考虑一个研究项目,你不断地产生和测试新的分子。当你获得更多的数据时,你会定期在稳步增长的数据集上重新训练你的模型,然后用它来预测其他尚未测试的分子的结果。验证这种方法是否有效的一个好方法是选择一个特定的截止日期,用当时拥有的所有数据训练模型,然后看看它预测后来生成的其他数据的效果如何。
Effect of Using Different Splitters
让我们看一个例子。我们将使用随机、支架和Butina分裂加载Tox21毒性数据集。对于每一个,我们训练一个模型,并在训练集和测试集上评估它。
代码
import deepchem as dc
splitters = ['random', 'scaffold', 'butina']
metric = dc.metrics.Metric(dc.metrics.roc_auc_score)
for splitter in splitters:
tasks, datasets, transformers = dc.molnet.load_tox21(featurizer='ECFP', split=splitter)
train_dataset, valid_dataset, test_dataset = datasets
model = dc.models.MultitaskClassifier(n_tasks=len(tasks), n_features=1024, layer_sizes=[1000])
model.fit(train_dataset, nb_epoch=10)
print('splitter:', splitter)
print('training set score:', model.evaluate(train_dataset, [metric], transformers))
print('test set score:', model.evaluate(test_dataset, [metric], transformers))
print()