PyTorch源码解读(一)torch.utils.data.DataLoader
阅读原文时间:2021年04月20日阅读:1

先简单的介绍一下DataLoader
它是PyTorch中数据读取的一个重要接口,该接口定义在dataloader.py中,只要是用PyTorch来训练模型基本都会用到该接口(除非用户重写…),该接口的目的:将自定义的Dataset根据batch size大小、是否shuffle等封装成一个Batch Size大小的Tensor,用于后面的训练。
源代码的地址https://pytorch.org/docs/master/data.html#single-and-multi-process-data-loading

看一下DataLoader给的源代码:

   torch.utils.data.DataLoader(
                            dataset,#数据加载
                            batch_size = 1,#批处理大小设置
                            shuffle = False,#是否进项洗牌操作
                            sampler = None,#指定数据加载中使用的索引/键的序列
                            batch_sampler = None,#和sampler类似
                            num_workers = 0,#是否进行多进程加载数据设置
                            collat​​e_fn = None,#是否合并样本列表以形成一小批Tensor
                            pin_memory = False,#如果True,数据加载器会在返回之前将Tensors复制到CUDA固定内存
                            drop_last = False,#True如果数据集大小不能被批处理大小整除,则设置为删除最后一个不完整的批处理。
                            timeout = 0,#如果为正,则为从工作人员收集批处理的超时值
                            worker_init_fn = None )

我们知道:DataLoader 构造函数最重要的参数是dataset,它表示要从中加载数据的数据集对象。PyTorch支持两种不同类型的数据集:
map-style datasets,
iterable-style datasets.
map-style datasets,
map-style datasets,是实现__getitem__()和 len()协议的数据集,并且表示从(可能是非整数的)索引/键到数据样本的映射。

下面对经常用到变量的设置进行简单的介绍

Data Loading Order and Sampler

对于可迭代样式的数据集,数据加载顺序完全由用户定义的iterable控制。这允许更容易地实现块读取和动态批量大小(例如,通过每次产生批量样本)。

map-style datasets,,torch.utils.data.Sampler 类用于指定数据加载中使用的索引/键的序列。它们表示索引到数据集的可迭代对象。例如,在具有随机梯度体面(SGD)的常见情况下,Sampler可以随机地置换索引列表并一次产生每个索引,或者为小批量SGD产生少量索引。
将根据shufflea 的参数自动构造顺序或混洗采样器DataLoader。或者,用户可以使用该sampler参数来指定自定义Sampler对象,该对象每次都会产生下一个要获取的索引/键。
Sampler可以将一次生成批处理索引列表的自定义作为batch_sampler参数传递。也可以通过batch_size和 drop_last参数启用自动批处理
iterable-style datasets是IterableDataset 实现__iter__()协议的子类的实例,并表示可迭代的数据样本。这种类型的数据集特别适用于随机读取昂贵或甚至不可能的情况,以及批量大小取决于获取的数据的情况。
例如,这样的数据集在被调用iter(dataset)时可以返回从数据库,远程服务器读取的数据流,甚至是实时生成的日志。
DataLoader支持通过参数个体取出的数据样本自动整理成批量 batch_size,drop_last和batch_sampler。

Loading Batched and Non-Batched Data

自动批处理(默认)
这是最常见的情况,并且对应于获取数据的小批量并将它们整理成批处理的样本,即,包含一维是批量维度的张量(通常是第一个)。
当batch_size(默认1)不是时None,数据加载器会生成批处理样本而不是单个样本。batch_size和 drop_lastarguments用于指定数据加载器如何获取批量数据集键。对于映射样式的数据集,用户也可以指定batch_sampler,一次生成一个键列表。

  1. batch_size与drop_last
    在batch_size与drop_last主要参数被用于构建batch_sampler从sampler。对于映射样式的数据集,它sampler由用户提供或基于shuffle参数构造。对于可迭代样式的数据集,它sampler是虚拟的无限数据集 。

  2. drop_last
    从具有 多处理的可迭代样式数据集中获取时 ,该 参数将删除每个工作程序的数据集副本的最后一个非完整批处理。

  3. 在使用sampler中的索引获取样本列表后,作为collate_fn参数传递的函数用于将样本列表整理为批次。
    在这种情况下,从映射样式数据集加载大致相当于:

    for indices in batch_sampler:
    yield collate_fn([dataset[i] for i in indices])

从可迭代样式的数据集加载大致相当于:

  dataset_iter = iter(dataset)
    for indices in batch_sampler:
        yield collate_fn([next(dataset_iter) for _ in indices])

自定义collate_fn可用于自定义排序,例如,将顺序数据填充到批次的最大长度。
禁用自动批处理
在某些情况下,用户可能希望在数据集代码中手动处理批处理,或者只是加载单个样本。例如,直接加载批量数据(例如,从数据库批量读取或读取连续的内存块),或批量大小取决于数据,或者程序设计用于单个样本。在这些情况下,最好不要使用自动批处理(其中collate_fn用于整理样本),但让数据加载器直接返回dataset对象的每个成员。
当两个batch_size和batch_sampler的None,自动配料被禁用。从dataset作为collate_fn参数传递的函数处理从中获得的每个样本。
禁用自动批处理时,默认情况下collate_fn只需将NumPy数组转换为PyTorch Tensors,并保持其他所有内容不变。
在这种情况下,从映射样式数据集加载大致相当于:

for index in sampler:
    yield collate_fn(dataset[index])

从可迭代样式的数据集加载大致相当于:

for data in iter(dataset):
    yield collate_fn(data)

Single- and Multi-process Data Loading

DataLoader默认使用单进程数据加载。
在Python进程中, 全局解释器锁(GIL) 阻止跨线程真正完全并行化Python代码。为了避免在数据加载时阻塞计算代码,PyTorch提供了一个简单的开关,只需将参数设置num_workers 为正整数即可执行多进程数据加载。
单进程数据加载(默认)
在此模式下,数据提取在DataLoader初始化的同一进程中完成 。因此,数据加载可能会阻止计算。然而,当用于在进程(例如,共享存储器,文件描述符)之间共享数据的资源有限时,或者当整个数据集很小并且可以完全加载到存储器中时,该模式可能是优选的。此外,单进程加载通常显示更可读的错误跟踪,因此对调试很有用。
多进程数据加载
将参数设置num_workers为正整数将打开具有指定数量的加载器工作进程的多进程数据加载。
在此模式下,每次DataLoader 创建a的迭代器(例如,当您调用时enumerate(dataloader)),都会num_workers 创建工作进程。
torch.utils.data.get_worker_info()返回工作进程中的各种有用信息(包括工作者ID,数据集副本,初始种子等),并None在主进程中返回。用户可以在数据集代码中使用此功能和/或worker_init_fn单独配置每个数据集副本,并确定代码是否在工作进程中运行。这在分片数据集时特别有用
***对于map-style datasets,***,主进程使用sampler并生成索引 并将它们发送给worker。因此,任何随机随机化都是在主进程中完成的,该进程通过为索引分配索引来指导加载。
对于iterable-style datasets,由于每个工作进程都获得了dataset对象的副本,因此 天真的多进程加载通常会导致重复的数据。使用torch.utils.data.get_worker_info()和/或 worker_init_fn,用户可以独立地配置每个副本。出于类似的原因,在多进程加载中,drop_last 参数会删除每个工作程序的可迭代样式数据集副本的最后一个非完整批处理。一旦达到迭代结束,或者迭代器变为垃圾收集,工作人员就会关闭。
**

注意

由于在多处理中使用CUDA和共享CUDA张量存在许多细微之处,因此通常不建议在多进程加载中返回CUDA张量(请参阅多处理中的CUDA)。相反,我们建议使用自动存储器固定(即设置 pin_memory=True),这样可以快速将数据传输到支持CUDA的GPU。

dataset(Dataset) - 从中​​加载数据的数据集。

batch_size(int,optional) - 每个批次要加载的样本数量(默认值:)1。

shuffle(bool,optional) - 设置为True在每个重新调整数据(默认值:) False。

sampler(Sampler,optional) - 定义从数据集中绘制样本的策略。如果指定,shuffle必须是False。

batch_sampler(Sampler,optional) - like sampler,但一次返回一批索引。互斥有batch_size, shuffle,sampler,和drop_last。

num_workers(int,optional) - 用于数据加载的子进程数。0表示数据将加载到主进程中。(默认值:0)

collat​​e_fn(callable ,optional) - 合并样本列表以形成一小批Tensor。从映射样式数据集使用批量加载时使用。

pin_memory(bool,optional) - 如果True,数据加载器会在返回之前将Tensors复制到CUDA固定内存中。如果您的数据元素是自定义类型,或者您collate_fn返回的是自定义类型的批处理,请参阅下面的示例。

drop_last(bool,optional) - True如果数据集大小不能被批处理大小整除,则设置为删除最后一个不完整的批处理。如果False且数据集的大小不能被批量大小整除,则最后一批将更小。(默认值:False)

timeout(数字,可选) - 如果为正,则为从工作人员收集批处理的超时值。应始终是非负面的。(默认值:0)

worker_init_fn(callable ,optional) - 如果没有None,则在播种后和数据加载之前,将在每个worker子进程上调用 this,并将worker id(int in )作为输入。(默认值:)[0, num_workers - 1]None

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章