Dataset and DataLoader
上一篇博客我们使用 Pytorch 加载了我们本地的糖尿病数据集,下面是上一篇博客的代码。
但是我们在训练的时候传入 model 是全部的训练数据集(x_data)。之前讨论过,使用梯度下降的时候,我们有几种选择,一种是批量梯度下降(全部的样本),一种是随机梯度下降(每次只用一个样本)。如果我们只用一个样本,我们可能会得到比较好的随机性,会帮助我们克服鞍点的问题(局部最优点),但是会导致时间过长,没法利用 GPU 和 CPU 的并行能力,所以训练的时间会过长。而对于批量梯度下降来说,它虽然计算速度非常快,但是它的性能方面会遇到一些问题。所以我们在深度学习中会用到 mini-batch (小批量)这样一种方法,mini-batch 就是每次不用全部的数据样本也不用 1 个数据样本,我们每次使用
k
k
k 个样本进行训练以达到均衡性能和训练时间的效果。
那么我们使用了 mini-batch 这种方式后,在 training cycle 代码中要使用嵌套循环,外层循环表示训练周期,内层循环表示一次 mini-batch。
接下来我们来看看定义:
- Epoch:就是所有样本都进行一次前向传播和反向传播的过程称作一次 Epoch。
- Batch-Size:每次训练时所使用的样本数,即进行一次前向传播和反向传播的过程中用到的样本数 。
- Iteration:内层循环迭代的次数。
下面举个简单的例子,假设现在有 10000 个样本,每次 mini-batch 中 k 为 1000,那么 1000 就是 Batch-Size,那么 Iteration 就是 10(10000 / 1000)。
首先我们做 mini-batch 的训练,首先得确定一些重要的参数,首先是 batch_size 是必须要指定的,在这个例子中,我们让 batch_size=2,另外我们为了提高训练的随机性,我们可以对数据集进行 shuffle(打乱位置),这样我们每次 mini-batch 生成的数据样本都是具有随机性的。
接下来我们看看 DataLoader 能帮我们做什么?当你有一个数据集,而且该数据集需要支持索引,也就是将来 DataLoader 能够访问到 Dataset 中的每一个元素,而且 DataLoader 还需要知道 Dataset 的长度。只要 Dataset 能够提供索引和长度,那么 DataLoader 就能够自动地进行小批量的数据集生成。
那么 DataLoader 的第一步是做 shuffle。
打乱顺序之后,我们开始进行分组。比如我们这个例子中 batch-size = 2,那么就将 sample 分成 2 个一组,一组就是一个 batch。这就是 DataLoader 的功能 Shuffle 和 Loader。
接下来我们看一下在代码的层面上怎么来实现 Dataset 和 DataLoader。首先值得注意的是 Dataset 是一个抽象类(抽象类不能实例化对象,只能被其它子类继承)。
然后 DataLoader 是用来帮助我们加载数据的,比如做 shuffle 和 batch-size,它自动帮助我们完成这个工作。那么我们就可以实例化一个 DataLoader 来帮助我们做这个工作。
接下来我们自定义了 DiabetesDataset 类,它是继承于 Dataset 类。
在该类中,我们需要实现几个方法。__init__
相当于构造函数,_getitem__
是实例化对象之后,该方法支持下标操作。就是可以通过 data[index] 将第 index 条数据获取到。
我们还需要实现 __len__
这个函数,该函数主要是获取 dataset 的长度。
一旦定义好了 DiabetesDataset 之后,我们就可以实例化一个对象 dataset。
DataLoader 是 Pytorch 提供的加载器。这个加载器我们一般初始化的时候,最常见的一般要设置 4 个初始值,第一个 dataset 数据集,第二个 batch-size,第三个 shuffle 是否要打乱顺序,第四个 num_workers 是否需要多进程运行,即并行化。
然后
然后接下来看一下 DiabetesDataset 数据集的实现。在 __init__
函数中添加了一个形参 filepath,filepath 就是本地数据集的路径。
接下来看一下 training cycle。training cycle 变成了一个双层循环。
下面就是整个代码。
到此我们就完成了用神经网络来对糖尿病数据集进行分类的程序。
其实 torchvision.datasets 中有很多数据集我们都可以去使用。
以上的数据集都是 torch.utils.data.Dataset 的子类。
下面以 MINST 数据集为例,展示怎么使用该数据集?