数据集和数据加载器
数据集和数据加载器(Dataset & DataLoader)
- 引子
- 什么是数据集
- Dataset概要
- 加载数据集
- 迭代和可视化数据集
- 创建自定义数据集
- 使用数据加载器为训练模型准备数据
- 遍历数据加载器
引子
- 模型的开发过程包括数据的读取、网络的设计、优化方法与损失函数的选择以及一些辅助的工具等。
Torchvision
- 计算机视觉是深度学习中最重要的一类应用,为了方便研究者使用,Pytorch团队专门开发了一个视觉工具包torchvision,这个包独立于Pytorch,需要通过pip install torchvision安装。
Torchvision
- torchvision主要包含以下三个部分:
- models:提供深度学习中各种经典网络的网络结构及预训练好的模型,包括AlexNet,VGG, ResNet,GoogLeNet等。
- datasets:提供常用数据集的dataset加载,设计上继承了torch.utils.data.Dataset的属性,主要包括MNIST,CIFAR-10,ImageNet等数据集
- transforms: 提供常用的数据预处理操作,主要包括对Tensor及PIL Image对象的操作
什么是数据集
数据集又称为资料集、数据集合或资料集合,是一种由数据所组成的集合。通常以表格形式(***.csv)出现。每一列代表一个特定变量。每一行都对应于某一成员的数据集的问题,每个数值被称为数据资料。
什么是数据集
- 深度学习的关键是训练。无论是从图像处理到语音识别,每个问题都有其独特的细微差别和方法,使用高质量的数据集可以改善模型的性能。
- 数据集分为三类——图像处理、自然语言处理和音频/语音处理。
什么是数据集
- 在开始深度学习任务时,需要准备一些数据集用来训练自己的算法。在选择数据集上面,最好使用可以快速下载的小的数据集,这种数据不用花太多的时间来训练模型。此外,也可以使用一些标准的数据集或者被广泛使用的数据集,这样可以把测试结果和别人的结果进行对比,以此来看是否取得进展。
什么是数据集-自然语言处理
- 文本分类
- 路透社新闻稿主题分类,这是路透社在 1982 年整理的一系列按照新闻主题归类的数据。
- IMDB电影评论情感分类。这是一个从 imdb.com 网站收集的电影评论的数据集,评论数据分为正向和负向。
- 文本摘要
- 法律案件报告数据集。这个数据集收集了 4000 个法律案件及其总结。
- TIPSTER 会议总结语料库。这个语料库收集了近 200 份文件及其摘要。
什么是数据集-ImageNet
- ImageNet是一个计算机视觉系统识别项目,是目前世界上图像识别最大的数据库。是美国斯坦福的计算机科学家李飞飞模拟人类的识别系统建立的,能够完成图像识别任务。目前已经包含14197122张图像,是已知的最大的图像数据库。每年的ImageNet大赛更是魂萦梦牵着国内外各个名校和大型IT公司以及网络巨头的心。
什么是数据集-MS COCO
- MS COCO的全称是Microsoft Common Objects in Context,起源于微软于2014年出资标注的Microsoft COCO数据集,与ImageNet竞赛一样,被视为是计算机视觉领域最受关注和最权威的比赛之一。
- COCO数据集是一个大型的、丰富的物体检测,分割和字幕数据集。这个数据集从复杂的日常场景中截取,图像包括91类目标,328,000影像和2,500,000个label。目前为止有语义分割的最大数据集,提供的类别有80类,有超过33万张图片,其中20万张有标注,整个数据集中个体的数目超过150万个。
Dataset概要
- 在解决深度学习问题的过程中,往往需要花费大量的精力去处理数据,包括图像、文本、语音或其他二进制数据等。数据的处理对训练神经网络来说十分重要,良好的数据处理不仅会加速模型训练,也会提高模型效果。
- 考虑到这一点,Pytorch 提供了几个高效便捷的工具(本节学习的Dataset和Dataloader),以便使用者进行数据处理或增强等操作,同时可通过并行化加速数据加载。
Dataset概要
- 用于处理数据样本的代码可能会变得混乱且难以维护;理想情况下,我们希望数据集代码与模型训练代码分离,以获得更好的可读性和模块化。
- Pytorch提供了两个数据原语:torch.utils.data.DataLoader和torch.utils.data.Dataset,允许您使用预加载的数据集和自己的数据。
- Dataset存储样本及其对应的标签,DataLoader迭代包装在Dataset周围,以便于访问样本。
Dataset概要
- Pytorch域库提供了许多预加载的数据集(如FashionMNIST ),这些数据集都是torch.utils.data.Dataset的子类(包括MNIST,CIFAR10/100,IMAGENET等数据集在设计上都继承了其相关属性)
- Pytorch针对特定数据实现特定的函数,这些函数可以用来原型化和基准化神经网络模型。
数据集的加载
- Pytorch中的 Dataset 类是一个抽象类,它可以用来表示数据集。我们通过继承 Dataset 类来自定义数据集的格式、大小和其它属性,后面就可以供 DataLoader 类直接使用。
数据集的加载
- 以下是如何从TorchVision加载时尚MNIST数据集的示例。《Fashion-MNIST》是Zalando文章图像的数据集,由60,000个训练样本和10,000个测试样本组成。每个示例包括一个28×28灰度图像和一个来自10个类别之一的关联标签。
数据集的加载
- 加载数据集所需的参数
- 我们使用以下参数加载FashionMNIST数据集:
- root 是存储训练/测试数据的路径。
- train 指定训练或测试数据集。
- download=True如果root不可用,则从互联网下载数据。
- transform 和 target_transform 指定特征和标签变换。
数据集的加载
import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt
#使用以下参数加载FashionMNIST数据集
training_data = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor()
)
test_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor()
)
迭代和可视化数据集
- 可以像python列表一样按索引提取数据集:training_data[index]。
- 使用matplotlib来可视化训练数据中的一些样本。
'''手动索引数据集'''
labels_map = {
0: "T-Shirt",
1: "Trouser",
2: "Pullover",
3: "Dress",
4: "Coat",
5: "Sandal",
6: "Shirt",
7: "Sneaker",
8: "Bag",
9: "Ankle Boot",
}
#绘制标签图谱
'''使用matplotlib来可视化训练数据中的一些样本'''
figure = plt.figure(figsize=(8, 8))
#生成一个图框,指定figure的宽和高分别为8英寸
cols, rows = 3, 3
for i in range(1, cols * rows + 1):
sample_idx = torch.randint(len(training_data), size=(1,)).item()
#生成随机整数
img, label = training_data[sample_idx]
#获取随机整数对应的img和label
figure.add_subplot(rows, cols, i)
#添加子图
plt.title(labels_map[label])
plt.axis("off")
plt.imshow(img.squeeze(), cmap="gray")
#将imgsqueeze成二维,然后显示
plt.show()
创建自定义数据集
在Pytorch当中,数据加载可通过自定义的数据集对象实现,数据集对象会被抽象为Dataset类,实现自定义的数据集需要继承Dataset,可以直接访问(调用)Dataset的静态属性和方法。
创建自定义数据集
- 自定义数据集类必须实现三个函数:
__init__
、__len__
、和__getitem__
。- FashionMNIST图像存储在目录img_dir中,它们的标签分别存储在CSV文件annotations_file中。
创建自定义数据集
import pandas as pd
from torchvision.io import read_image
class CustomImageDataset(Dataset):
#初始化包含图像、注释文件和转换的目录
def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
self.img_labels = pd.read_csv(annotations_file)
self.img_dir = img_dir
self.transform = transform
self.target_transform = target_transform
#返回数据集中的样本数
def __len__(self):
return len(self.img_labels)
#加载并返回数据集中给定索引idx处的样本
def __getitem__(self, idx):
img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
image = read_image(img_path)
label = self.img_labels.iloc[idx, 1]
if self.transform:
image = self.transform(image)
if self.target_transform:
label = self.target_transform(label)
return image, label
创建自定义数据集
__init__
函数在实例化数据集对象时运行一次。- 初始化过程包含图像初始化、注释文件的初始化、transform的初始化。
创建自定义数据集
# __init__ 函数初始化过程包含图像初始化、注释文件的初始化、transform的初始化
tshirt1.jpg, 0
tshirt2.jpg, 0
......
ankleboot999.jpg, 9
def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
self.img_labels = pd.read_csv(annotations_file)
self.img_dir = img_dir
self.transform = transform
self.target_transform = target_transform
创建自定义数据集
#__len__ 函数返回数据集中的样本数
def __len__(self):
return len(self.img_labels)
创建自定义数据集
- 函数__getitem__加载并返回数据集中给定索引idx处的样本。基于索引,它识别图像在磁盘上的位置,使用read_image将其转换为张量,从self.img_labels中的csv数据中检索相应的标签,并返回元组中的张量图像和相应标签。
创建自定义数据集
#函数__getitem__加载并返回数据集中给定索引idx处的样本
def __getitem__(self, idx):
img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
image = read_image(img_path)
label = self.img_labels.iloc[idx, 1]
if self.transform:
image = self.transform(image)
if self.target_transform:
label = self.target_transform(label)
return image, label
使用数据加载器为训练模型准备数据
- Dataset检索数据集的特征并一次标注一个样本的标签。在训练模型时,我们通常希望传递“迷你批次”中的样本,在每个时期重新排列数据以减少模型过度拟合,并使用Python的多重处理来加速数据检索。
- DataLoader是一个迭代器 ,它在一个简单的API中为我们抽象了这种复杂性。
使用数据加载器为训练模型准备数据
Dataset只负责数据的抽象,一次调用__getitem__只返回一个样本,而在训练神经网络时,需要对一个batch的数据进行操作,同时还需要对数据进行shuffle或者并行加速等操作。对此,Pytorch中提供了DataLoader帮助我们实现这些功能。
使用数据加载器为训练模型准备数据
from torch.utils.data import DataLoader
train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)
遍历数据加载器
- 我们已经将该数据集加载到DataLoader中,并可以根据需要遍历该数据集。下面的每个迭代返回一批train_features和train_labels(分别包含batch_size=64个要素和标注)。因为我们指定shuffle=True,所以在我们遍历所有批处理之后,数据被打乱(为了更好地控制数据加载顺序,看一下采样器)。
遍历数据加载器
#使用shuffle在batch所有batch后打乱数据
# Display image and label.
train_features, train_labels = next(iter(train_dataloader))
print(f"Feature batch shape: {train_features.size()}")
print(f"Labels batch shape: {train_labels.size()}")
img = train_features[0].squeeze()
label = train_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"Label: {label}")