01 - Dataset和DataLoader
从前有两个类
在PyTorch中,Dataset和DataLoader是两个关键的类,用于处理数据加载和预处理,特别是在训练神经网络时。
Dataset类
Dataset是一个抽象类,用于表示数据集。它提供了一个接口,让用户可以自定义数据集的加载和预处理逻辑。用户需要继承Dataset类,并实现__len__和__getitem__方法来定义数据集的大小和如何获取单个样本。Dataset的目的是为了统一数据加载的接口,使得不同类型的数据可以以相同的方式被加载和使用。
它提供了一种方式去获取数据及其label。
DataLoader类
DataLoader用于将Dataset对象封装成可迭代的数据加载器。它提供了批量加载数据、数据打乱、并行加载等功能。DataLoader使得用户可以更方便地迭代训练数据集,并且支持多线程和多进程的数据加载,提高了数据加载的效率。
它为神经网络提供不同的数据形式。
Dataset
理论
常见的数据组成形式:
- label以文件夹命名区分。
- label和data分开,label记录在文本中,文本与数据文件名对应。
- 以文件名作为label。
- 这是一个表示数据集的抽象类,用于表示从键到数据样本的映射。所有表示从键到数据样本的数据集都应该是它的子类。
- 所有子类都应该重写
__getitem__
方法,以支持根据给定键获取数据样本。此外,子类还可以选择重写__len__
方法,该方法期望返回数据集的大小,许多torch.utils.data.Sampler
实现和torch.utils.data.DataLoader
的默认选项都会使用这个方法。子类还可以选择实现__getitems__
方法,用于加速批量样本加载。这个方法接受样本批次的索引列表,并返回样本列表。 - 对于
torch.utils.data.DataLoader
默认情况下会构建一个索引采样器,该采样器生成整数索引。如果要将其用于具有非整数索引/键的映射样式数据集,则必须提供自定义采样器。 - 类
Dataset
是typing.Generic
的子类,这意味着它是一个泛型类。它具有一个类型参数T_co
,表示协变的类型。 - 该类定义了
__add__
和__getitem__
方法。__add__
方法用于连接两个数据集。__getitem__
方法用于根据索引获取数据集中的样本。 - 该类还具有一些数据描述符,如
__dict__
和__weakref__
,以及一些类属性,如__orig_bases__
和__parameters__
。 - 还有一些从
typing.Generic
继承的类方法和静态方法,如__class_getitem__
和__init_subclass__
。
实战
from torch.utils.data import Dataset
from PIL import Image
import os
class Mydata(Dataset):
def __init__(self, root_dir, label_dir):
self.root_dir = root_dir
self.label_dir = label_dir
self.path = os.path.join(self.root_dir, self.label_dir)
self.img_path = os.listdir(self.path)
def __getitem__(self, idx):
img_name = self.img_path[idx]
img_item_path = os.path.join(self.root_dir,self.label_dir , img_name)
img = Image.open(img_item_path)
label = self.label_dir
return img, label
def __len__(self):
return len(self.img_path)
root_dir = 'PyTorch 深度学习快速入门教程/数据集/hymenoptera_data/train'
ants_label_dir = 'ants'
bees_label_dir = 'bees'
ants_dataset = Mydata(root_dir, ants_label_dir)
bees_dataset = Mydata(root_dir, bees_label_dir)
train_dataset = ants_dataset + bees_dataset
img1, label1 = train_dataset[123]
img1.show()
DataLoader
理论
在 PyTorch 中,DataLoader 是一个用于封装数据集(Dataset)并提供数据加载的工具。它负责从数据集中加载数据,并按照指定的配置对数据进行批处理、打乱和并行加载等操作。DataLoader 提供了一个可迭代的接口,使得在训练过程中可以方便地从数据集中逐批获取数据。
DataLoader 使用 Dataset 来加载数据。在创建 DataLoader 对象时,需要将 Dataset 对象作为参数传入,然后通过设置一些参数(例如批大小、是否打乱数据等)来配置 DataLoader,最终 DataLoader 将根据这些配置从 Dataset 中加载数据。因此,DataLoader 是 Dataset 的一个包装器,用于提供更灵活、更高效的数据加载方式,使得在训练模型时可以更方便地使用数据。
实战
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor())
test_loader = DataLoader(dataset=test_data, batch_size=4, shuffle=True, num_workers=0, drop_last=False)
# 测试集中第一张图片
img, target = test_data[0]
writer = SummaryWriter("dataloader")
step = 0
for data in test_loader:
imgs, targets= data
# print(imgs.shape)
# print(targets)
writer.add_image("test_data", imgs, step)
step += 1
writer.close()
- dataset: 这是要加载的数据集。
- batch_size: 批大小,即每次从数据集中加载多少个样本。
- shuffle: 是否在每个 epoch 时对数据进行打乱。如果设置为 True,则每个 epoch 会随机打乱数据,这有助于增加模型训练的随机性,防止模型过度拟合训练集。
- num_workers: 用于数据加载的子进程数。如果设置为大于 0 的值,则会启动多个子进程来加载数据,可以加快数据加载速度。在实际使用中,通常会将其设置为 CPU 的逻辑核心数目。在这个例子中,您设置为 0,表示不使用额外的子进程,所有数据加载操作都在主进程中完成。
- drop_last: 如果数据集的大小不能被批大小整除,是否丢弃最后一个不完整的批次。如果设置为 True,则会丢弃不完整的批次;如果设置为 False,则会保留不完整的批次。在这个例子中,您设置为 False,即保留不完整的批次。