数据是机器学习的核心。本教程介绍 DeepChem 用于存储和管理数据的“Dataset”类,它为处理大量数据提供了简单且功能强大的功能,它支持在 Python 框架(如 NumPy、Pandas、TensorFlow 和 PyTorch)交互。
!pip install --pre deepchem
我们现在可以导入 deepchem 包来试一试。
import deepchem as dc
dc.__version__
'2.4.0-rc1.dev'
在上一个教程中,我们加载了分子溶解度的 Delaney 数据集,让我们重新加载它。
tasks, datasets, transformers = dc.molnet.load_delaney(featurizer='GraphConv')
train_dataset, valid_dataset, test_dataset = datasets
我们现在有三个数据集对象:训练集、验证集和测试集。它们各自包含什么信息?我们可以通过打印出其中一个的字符串来了解。
print(test_dataset)
<DiskDataset X.shape: (113,), y.shape: (113, 1), w.shape: (113, 1), ids: ['C1c2ccccc2c3ccc4ccccc4c13' 'COc1ccccc1Cl'
'COP(=S)(OC)Oc1cc(Cl)c(Br)cc1Cl' ... 'CCSCCSP(=S)(OC)OC' 'CCC(C)C'
'COP(=O)(OC)OC(=CCl)c1cc(Cl)c(Cl)cc1Cl'], task_names: ['measured log solubility in mols per litre']>
那里有很多信息,所以让我们从头开始。它以标签“DiskDataset”开头。数据集是一个抽象类,它有几个子类,对应于不同的数据存储方式。
•DiskDataset 是已保存到磁盘的数据集。数据以可以高效访问的方式存储,即使数据总量远大于计算机内存。
•NumpyDataset 是一个内存数据集,将所有数据保存在 NumPy 数组中。在处理完全适合内存的中小型数据集时,它是一个有用的工具。
•ImageDataset 是一个更专业的类,它将部分或全部数据存储在磁盘上的图像文件中。在处理以图像作为输入或输出的模型时,它很有用。
现在我们看数据集的内容,每个数据集都存储一个 samples 列表,粗略地说,样本是单个数据点。在这种情况下,每个样本都是一个分子。在其他数据集中,样本可能对应于实验分析、细胞系、图像或许多其他事物。对于每个样本,数据集存储以下信息。
•features,称为 X。这是应该输入到模型中以表示样本的输入。
•labels,称为 y。这是模型的期望输出。在训练期间,它会尝试使每个样本的模型输出尽可能接近“y”。
•权重,称为“w”。这可用于指示某些数据值比其他数据值更重要。在后面的教程中,我们将看到有关其用途的示例。
•ID,它是样本的唯一标识符。这可以是任何东西,只要它是唯一的。有时它只是一个整数索引,但在这个数据集中,ID 是一个描述分子的 SMILES 字符串。
请注意,“X”、“y”和“w”的第一维大小均为 113。这意味着该数据集包含 113 个样本。
输出中列出的最后一条信息是“task_names”。一些数据集包含每个样本的多条信息。例如,如果一个样本代表一个分子,则数据集可能会记录对该分子进行的多个不同实验的结果。这个数据集只有一个任务:“测量对数溶解度,单位为摩尔每升”。另请注意,y 和 w 的形状均为 (113, 1)。这些数组的第二维通常与任务数相匹配。
有许多方法可以访问数据集中包含的数据。最简单的就是直接访问“X”、“y”、“w”和“ids”属性。其中每一个都以 NumPy 数组的形式返回相应的信息。
test_dataset.y
这是一种访问数据的非常简单的方法,但是您在使用它时应该非常小心。这需要一次将所有样本的数据加载到内存中,这对于像这样的小数据集来说很好,但对于大数据集来说,它很容易占用比你拥有的更多的内存。
更好的方法是迭代数据集。这让它一次只加载一点数据,处理它,然后在加载下一位之前释放内存。您可以使用 itersamples() 方法一次迭代一个样本。
for X, y, w, id in test_dataset.itersamples():
print(y, id)
大多数深度学习模型可以同时处理一批多个样本。您可以使用 iterbatches() 迭代样本批次。
for X, y, w, ids in test_dataset.iterbatches(batch_size=50):
print(y.shape)
(50, 1)
(50, 1)
(13, 1)
iterbatches() 具有其他在训练模型时有用的功能。例如,iterbatches(batch_size=100, epochs=10, deterministic=False) 将在整个数据集上迭代十次,每次样本都以不同的随机顺序排列。
数据集还可以使用 TensorFlow 和 PyTorch 的标准接口公开数据。要获取 tensorflow.data.Dataset,请调用 make_tf_dataset()。要获取 torch.utils.data.IterableDataset,请调用 make_pytorch_dataset()。有关详细信息,请参阅 API 文档。
访问数据的最后一种方式是to_dataframe()。这会将数据复 制到 Pandas DataFrame 中。这需要一次将所有数据存储在内存中,因此您应该只将它用于小型数据集。
test_dataset.to_dataframe()
现在让我们谈谈如何创建自己的数据集。创建“NumpyDataset”非常简单,只需将包含数据的数组传递给构造函数即可。让我们创建一些随机数组,然后将它们包装在 NumpyDataset 中。
import numpy as np
X = np.random.random((10, 5))
y = np.random.random((10, 2))
dataset = dc.data.NumpyDataset(X=X, y=y)
print(dataset)
<NumpyDataset X.shape: (10, 5), y.shape: (10, 2), w.shape: (10, 1), ids: [0 1 2 3 4 5 6 7 8 9], task_names: [0 1]>
请注意,我们没有指定权重或 ID。这些是可选的,就此而言,“y”也是可选的,只有“X”是必需的,由于我们将它们排除在外,它会自动为我们构建“w”和“ids”数组,将所有权重设置为 1,并将 ID 设置为整数索引。
dataset.to_dataframe()
创建一个 DiskDataset 怎么样?如果您有 NumPy 数组中的数据,则可以调用 DiskDataset.from_numpy() 将其保存到磁盘。由于这只是一个教程,我们将把它保存到一个临时目录中。
import tempfile
with tempfile.TemporaryDirectory() as data_dir:
disk_dataset = dc.data.DiskDataset.from_numpy(X=X, y=y, data_dir=data_dir)
print(disk_dataset)
<DiskDataset X.shape: (10, 5), y.shape: (10, 2), w.shape: (10, 1), ids: [0 1 2 3 4 5 6 7 8 9], task_names: [0 1]>
无法放入内存的较大数据集怎么办?
如果磁盘上有一些包含数亿个分子数据的大文件怎么办?
DeepChem 的“DataLoader”框架可以为您自动完成大部分工作,只不过创建 DiskDataset 的过程稍微复杂一些。这是一个更大的主题,所以我们将在以后的教程中进行讲解。