type
status
date
slug
summary
tags
category
icon
password
Property
一般来说PyTorch中深度学习训练的数据读取流程是这样的:
- 创建Dateset
- Dataset传递给DataLoader
- DataLoader迭代产生训练数据提供给模型
Dataset
pytorch自带数据集
torchvision.datasets
模块提供了一些已有数据集的直接导入:- 用于image classification:
手写字符识别:
EMNIST、MNIST、QMNIST、USPS、SVHN、KMNIST、Omniglot
实物分类:
Fashion MNIST、CIFAR、LSUN、SLT-10、ImageNet
人脸识别:
CelebA
场景分类:
LSUN、Places365
- 用于object detection:
SVHN、VOCDetection、COCODetection
- 用于semantic/instance segmentation:
语义分割:
Cityscapes、VOCSegmentation
语义边界:
SBD
- 用于image captioning:
Flickr、COCOCaption
- 用于video classification:
HMDB51、Kinetics
- 用于3D reconstruction:
PhotoTour
- 用于shadow detectors:
SBU
root
: 数据集的本地保存位置,路径不存在会自动创建download
:True
优先检查是否已下载数据集,如果已有数据集则不会重复下载,否则下载到该位置。 train
:True
下载训练集,否则下载测试集 transform
:该参数用于数据预处理,数据增强target_transform
:该参数用于标签的预处理,通常默认使用None
即可,也可改写此项转换成one-hot
编码自建数据集
pytorch提供了一个快捷的构建数据集的函数
torchvision.dataset.ImageFolder
,指定该函数的根目录可以快速根据次级目录及其中图片构建数据集这种方式固然方便快捷,但针对不同的机器学习问题所采用的数据集往往也有一些独特之处,需要一种通用的办法,并根据实际情况做具体的改变。我们应该读取每一个图片并且保存每张图片的张量(tensor)和它对应的标签(target)并且将它们保存到一个数据结构之中以便后续使用。可以使用字典+列表保存所有图片
os.walk
假设我们的test文件夹有如下的目录结构:
也可以利用os.walk输出test文件夹下指定后缀名(比如.txt)文件:
接下来我们已经可以使用训练集和测试集了,但是这种数据结构在使用时方式只是单进程,单次搜索,当内存不足以完整装入全部数据时效率低下,而且
batch size = 1
图片之间差距过大时梯度震荡强烈,不利于收敛。显然我们需要寻求一种更好更专业的方式,pytorch为我们提供了
Dataset
类接口。torch.utils.data.Dataset
是一个表示数据集的抽象类。任何自定义的数据集都需要继承这个类并覆写相关方法。所谓数据集,其实就是一个负责处理索引到样本映射的一个类
Pytorch提供两种数据集: Map式数据集 Iterable式数据集
Map式数据集
一个Map式的数据集必须要重写getitem(self, index),len(self) 两个内建方法
这样一个数据集dataset,举个例子,当使用dataset[idx]命令时,可以在你的硬盘中读取你的数据集中第idx张图片以及其标签(如果有的话);len(dataset)则会返回这个数据集的容量。
自定义类大致是这样的:
上述代码将数据读入的步骤放在了初始化阶段,这样做的劣势是开始时需要把所有数据读一遍,初始化时间较长,如果数据量巨大内存消耗巨大。优点在多轮迭代的过程中不需要重复读数据,只需一轮io操作,对于多轮训练节约时间。
还有一种做法是把数据的读入放在
__getitem__
中,这样做的优点是每次都只读一个,响应快,几乎不占内存。劣势是在多轮迭代中每次都需要反复中断读入数据,整体来说时间较长Iterable式数据集
一个Iterable(迭代)式数据集是抽象类
data.IterableDataset
的子类,并且覆写了__iter__方法成为一个迭代器。这种数据集主要用于数据大小未知,或者以流的形式的输入,本地文件不固定的情况,需要以迭代的方式来获取样本索引。DataLoader
现在我们已经自建了一个数据集并且实现了一个数据结构可以用来使用了,但是还存在一些不足之处。也就是前文提到过的
batch size = 1
,并且我们没有充分利用多进程导入数据。pytorch提供了DataLoader
来进一步对数据集二次操作参数介绍:
dataset
定义好的Map式或者Iterable式数据集
batch_size
一个batch含有多少样本 (default: 1)
shuffle
每一个epoch的batch样本是相同还是随机 (default: False),True则每次调用时打乱
sampler
决定数据集中采样的方法. 如果有,则shuffle参数必须为False
自带的Sampler:
SequentialSampler
RandomSampler
SubsetRandomSampler
WeightedRandomSampler
batch_sampler
和 sampler 类似,但是一次返回的是一个batch内所有样本的index。和 batch_size, shuffle, sampler, and drop_last 三个参数互斥。
num_workers
多少个子程序同时工作来获取数据,多线程。 (default: 0)
collate_fn
合并样本列表以形成小批量
pin_memory
如果为True,数据加载器在返回前将张量复制到CUDA固定内存中
drop_last
如果数据集大小不能被batch_size整除,设置为True可删除最后一个不完整的批处理。如果设为False并且数据集的大小不能被batch_size整除,则最后一个batch将更小。(default: False)
timeout
如果是正数,表明等待从worker进程中收集一个batch等待的时间,若超出设定的时间还没有收集到,那就不收集这个内容了。这个numeric应总是大于等于0。 (default: 0)
worker_init_fn
每个worker初始化函数 (default: None)
TensorDataset
TensorDataset 可以用来对 tensor 进行打包,就好像 python 中的 zip 功能。该类通过每一个 tensor 的第一个维度进行索引。因此,该类中的 tensor 第一维度必须相等. 另外:TensorDataset 中的参数必须是 tensor