pytorch中的数据导入之DataLoader和Dataset的使用介绍


在使用Pytorch构建和训练模型的过程中,经常需要把原始数据(图片、文本等)转换为张量的格式。对于小数据集,我们可以手动导入,但是在深度学习中,数据集往往是比较大的,这时pytorch的数据导入功能便发挥了作用,Pytorch导入数据主要依靠 torch.utils.data.DataLoadertorch.utils.data.Dataset这两个类来完成。

  1. torch.utils.data.Dataset:这是一个抽象类,所以我们需要对其进行派生,从而使用其派生类来创建数据集。最主要的两个函数实现为__Len____getitem__
  • __init__:可以在这里设置加载的data和label。
  • __Len__:获取数据集大小
  • __getitem__:根据索引获取一条训练的数据和标签。
  1. torch.utils.data.DataLoader:接收torch.utils.data.Dataset作为输入,得到DataLoader,它是一个迭代器,方便我们去多线程地读取数据,并且可以实现batch以及shuffle的读取等。

pytorch 的数据加载到模型的操作顺序如下:

(看完本文章,再回过头看这部分会更清晰):

  1. 创建一个 Dataset 对象
  2. 创建一个 DataLoader 对象
  3. 循环这个 DataLoader 对象,将img, label加载到模型中进行训练
dataset = MyDataset()
dataloader = DataLoader(dataset)
num_epoches = 100
for epoch in range(num_epoches):
    for img, label in dataloader:
        ....

1. 构建数据集-torch.utils.data.Dataset

torch.utils.data.Dataset可通过两种方式生成,一种是通过内置的下载功能,另一种便是自己实现。下载功能需要借助一些其他的包,比如torchvision,下载CIFAR10数据格式大致如下:

import torch
import torchvision

cf10_data = torchvision.datasets.CIFAR10('dataset/cifar/', download=True)

下面我们主要介绍怎么创建一个属于自己的数据集。

任何自定义的数据集都要继承自torch.utils.data.Dataset,然后重写两个函数:__len__(self)__getitem__(self, idx)

下面是一个简单的自定义小型数据集,以期能够理解它的创建方式。注意下面的示例中并没有通过__init__传入data和label,而是在内部创建的。

import torch
from torch.utils.data import Dataset

class myDataset(Dataset):
    def __init__(self):
        #创建5*2的数据集
        self.data = torch.tensor([[1,2],[3,4],[2,1],[3,4],[4,5]])  
        #5个数据的标签
        self.label = torch.tensor([0,1,0,1,2])
    
    #根据索引获取data和label
    def __getitem__(self,index):
        return self.data[index], self.label[index] #以元组的形式返回

    #获取数据集的大小
    def __len__(self):
        return len(self.data)

data = myDataset()
print(f'data size is : {len(data)}')

print(data[1]) #获取索引为1的data和label

输出:

data size is : 5
(tensor([3, 4]), tensor(1))

2. 数据载入-torch.utils.data.DataLoader

torch.utils.data.Dataset通过__getitem__获取单个数据,如果希望获取批量数据、shuffle或者其它的一些操作,那么就要由torch.utils.data.DataLoader来实现了,它的实现形式如下:

data.DataLoader(
    dataset,
    batch_size = 50,
    shuffle = False,
    sampler=None,
    batch_sampler = None,
    num_workers = 0,
    collate_fn = 
    pin_memory = False,
    drop_last = False,
    timeout = 0,
    worker_init_fn = None,
)
  • dataset:待传入的数据集,也就是上面自己实现的myData。
  • batch_size:每个batch有多少个样本
  • shuffle:代表数据会不会被随机打乱,在每个epoch开始的时候,对数据进行重新排序
  • sampler:自定义从数据集中取样本的策略,如果指定这个参数,那么shuffle必须为False
  • batch_sampler:类似于sampler,不过返回的是一个迷你批次的数据索引。
  • num_workers:是数据载入器使用的进程数目,默认为0。
  • collate_fn:用于自定义sample 如何形成 batch sample 的函数。因为getitem只是得到一条数据,collate_fun组成一个batch数据
  • pin_memory:如果设置为True,那么data loader将会在返回它们之前,将tensors拷贝到CUDA中的固定内存(CUDA pinned memory)中。
  • drop_last:如果设置为true,那么最后的batch的大小如果小于batch_size,那么则会丢弃。
  • timeout:如果是正数,表明等待从worker进程中收集一个batch等待的时间,若超出设定的时间还没有收集到,那就不收集这个内容了。这个numeric应总是大于等于0。默认为0。
  • worker_init_fn:它决定了每个数据载入的子进程开始时运行的函数

按照上面的Dataset,使用DataLoader加载数据示例如下,因为设置了drop_last = True,所以最后一个batch会被丢弃。

from torch.utils.data import DataLoader
data = myDataset()

my_loader = DataLoader(data,batch_size=2,shuffle=False,num_workers = 0,drop_last=True)
for step,train_data in enumerate(my_loader):
    Data,Label = train_data
    print("step:",step)
    print("data:",Data)
    print("Label:",Label)

输出:

step: 0
data: tensor([[1, 2],
        [3, 4]])
Label: tensor([0, 1])
step: 1
data: tensor([[2, 1],
        [3, 4]])
Label: tensor([0, 1])

3. 把数据放入GPU中

在Dataset和DataLoader的地方都可以实现把数据放入GPU,下面分别进行介绍。

  • Dataset阶段把数据放入GPU

如果在此阶段把数据放入GPU,则此阶段必须把num_workers设置为0,要不然会报错。此阶段的操作需要在__getitem__中实现,实现过程大致如下。

    def __getitem__(self, index):
        data = torch.Tensor(self.Data[index])
        label = torch.IntTensor(self.Label[index])
        if torch.cuda.is_available():
            data = data.cuda()
            label = label.cuda()
        return data, label
  • DataLoader阶段把数据放入GPU

这种实现方式就没有特别需要注意的地方,直接把tensor放入GPU即可,所以推荐使用这种实现方式,如下所示。

data = myDataset()

my_loader = DataLoader(data,2,shuffle=False,num_workers = 0,drop_last=True)
for step,train_data in enumerate(my_loader):
    Data,Label = train_data
    #把数据放在GPU中
    if torch.cuda.is_available():
        data = data.cuda()
        label = label.cuda()
    print("step:",step)
    print("data:",Data)
    print("Label:",Label)
  • 49
    点赞
  • 130
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
PyTorch数据读取是构建深度学习模型的重要一环。为了高效处理大规模数据集,PyTorch提供了三个主要的工具:DatasetDataLoader和TensorDatasetDataset是一个抽象类,用于自定义数据集。我们可以继承Dataset类,并重写其的__len__和__getitem__方法来实现自己的数据加载逻辑。__len__方法返回数据集的大小,而__getitem__方法根据给定的索引返回样本和对应的标签。通过自定义Dataset类,我们可以灵活地处理各种类型的数据集。 DataLoader数据加载器,用于对数据集进行批量加载。它接收一个Dataset对象作为输入,并可以定义一些参数例如批量大小、是否乱序等。DataLoader能够自动将数据集划分为小批次,将数据转换为Tensor形式,然后通过迭代器的方式供模型训练使用DataLoader数据准备和模型训练的过程起到了桥梁作用。 TensorDataset是一个继承自Dataset的类,在构造时将输入数据和目标数据封装成Tensor。通过TensorDataset,我们可以方便地处理Tensor格式的数据集。TensorDataset可以将多个Tensor按行对齐,即将第i个样本从各个Tensor取出,构成一个新的Tensor作为数据集的一部分。这对于处理多输入或者多标签的情况非常有用。 总结来说,Dataset提供了自定义数据集的接口,DataLoader提供了批量加载数据集的能力,而TensorDataset则使得我们可以方便地处理Tensor格式的数据集。这三个工具的配合使用可以使得数据处理变得更加方便和高效。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非晚非晚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值