Pytorch之DataLoader & Dataset、datasets、models、transforms的认识和学习

利用PyTorch框架来开发深度学习算法时几个基础的模块

  • Dataset & DataLoader
  • datasets
  • models
  • transforms

在利用PyTorch开始进入深度学习“大坑”的时候必须将以上的几个模块熟练掌握,这样才可以运用自如的写自己的算法或者魔改别人算法的code,下面将对以上几个模块逐一介绍其重点和一些注意事项。

Dataset & DataLoader

基础概念

Dataset & DataLoader 属于 torch中 torch.utils.data 中的模块,要使用 Dataset & DataLoader时, 必须预先导入,具体代码如下所示:

# DataLoader & Dataset 同时使用时一起导入
from torch.utils.data import Dataset Dataloader

# DataLoader & Dataset 不是同时使用时,需要哪一个就导入哪一个
# 利用 Dataset 来构建自己的数据集时,必须导入Dataset
from torch.utils.data import Dataset
# 利用DataLoader 来加载自己的数据集或者官方提供的数据集时,必须导入Dataloader
from torch.utils.data import Dataloader

Dataset 是一个抽象类,为了能够方便的读取,需要将要使用的数据包装为Dataset类。
自定义的Dataset需要继承它并且实现两个成员方法:

  1. getitem() 该方法定义用索引(0 到 len(self))获取一条数据或一个样本
  2. len() 该方法返回数据集的总长度
    DataLoader为我们提供了对Dataset的读取操作,常用参数有:batch_size(每个batch的大小)、 shuffle(是否进行shuffle操作)、 num_workers(加载数据的时候使用几个子进程)。

自定义数据集 1

# 使用kaggle上的一个竞赛bluebook for bulldozers自定义一个数据集
import torch
from torch.utils.data import Dataset  # 导入抽象类Dataset
import pandas as pd  # 本质是使用pandas进行处理,只是相当于进行了封装。

# 定义一个数据集
class BulldozerDataset(Dataset):
    """ 数据集演示 """
    def __init__(self, csv_file):
        # 实现初始化方法,在初始化的时候将数据读载入
        # 数据保存在self.df中
        self.df=pd.read_csv(csv_file)
    def __len__(self):  # 本质替换定义了len()函数的作用
        # 返回df的长度
        return len(self.df)
    def __getitem__(self, idx):  # 本质定义了替换iloc[]的作用
        # 根据 idx 返回一行数据
        return self.df.iloc[idx].SalePrice
# 实例化一个对象访问它
ds_demo= BulldozerDataset('median_benchmark.csv')  #传入一个.csv文件
#实现了 __len__ 方法所以可以直接使用len获取数据总数
len(ds_demo)
# output: 11573
#用索引可以直接访问对应的数据,对应 __getitem__ 方法
ds_demo[0]
# output: 24000.0 

读取自定义数据集 1

# 对刚刚上面建立的Dataset,利用DataLoader 进行读取。
dl = torch.utils.data.DataLoader(ds_demo, batch_size=10, shuffle=True, num_workers=0)
# DataLoader返回的是一个可迭代对象,我们可以使用迭代器分次获取数据
# DataLoader本质是一个类,用来实现复杂的函数功能和其他功能
# .csv(原始数据)--->ds_demo(Dataset类对象)--->dl(DataLoader类对象)
idata=iter(dl)  # iter() 迭代函数
print(next(idata))
# 更常见的用法是使用for循环对其进行遍历
for i, data in enumerate(dl):
    print(i,data)
    # 为了节约空间,这里只循环一遍
    break
# output:0 tensor([24000., 24000., 24000., 24000., 24000., 24000., 24000., 24000., 24000., 24000.], dtype=torch.float64)
# 第一个维度是batch_size==10,每一个元素其实是一个实际的数据

自定义数据集 2

import os
from PIL import Image
from torch.utils.data import Dataset


class PatchDataset(Dataset):
    def __init__(self, data_dir, transform=None):
        """
        :param data_dir: 数据集所在路径
        :param transform: 数据预处理
        """

        self.data_info = self.get_img_info(data_dir)
        self.transform = transform

    def __getitem__(self, item):
        path_img, label = self.data_info[item]
        image = Image.open(path_img).convert('RGB')
        if self.transform is not None:
            image = self.transform(image)

        return image, label

    def __len__(self):
        return len(self.data_info)

    @staticmethod
    def get_img_info(data_dir):
        path_dir = os.path.join(data_dir, 'train_dataset.txt')
        data_info = []
        with open(path_dir) as file:
            lines = file.readlines()
            for line in lines:
                data_info.append(line.strip('\n').split(' '))
        return data_info

自定义数据集3

from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, utils

normalize = transforms.Normalize(
    mean=[0.485, 0.456, 0.406],
    std=[0.229, 0.224, 0.225]
)
preprocess = transforms.Compose([
    #transforms.Scale(256),
    #transforms.CenterCrop(224),
    transforms.ToTensor(),
    normalize
])

def default_loader(path):
    img_pil =  Image.open(path)
    img_pil = img_pil.resize((224,224))
    img_tensor = preprocess(img_pil)
    return img_tensor

#当然出来的时候已经全都变成了tensor
class trainset(Dataset):
    def __init__(self, loader=default_loader):
        #定义好 image 的路径
        self.images = file_train
        self.target = number_train
        self.loader = loader

    def __getitem__(self, index):
        fn = self.images[index]
        img = self.loader(fn)
        target = self.target[index]
        return img,target

    def __len__(self):
        return len(self.images)

官方文档写自定义数据集

A custom Dataset class must implement three functions: init, len, and getitem.

  • The init function is run once when instantiating the Dataset object. 通常是第一次加载数据。
  • The len function returns the number of samples in our dataset. 获取该数据集的长度。
  • The getitem function loads and returns a sample from the dataset at the given index idx. 根据索引获取数据集中的数据。
# A example
# The FashionMNIST images are stored in a directory img_dir, and their labels are stored separately in a CSV file annotations_file.
import os
import pandas as pd
from torchvision.io import read_image # 该函数读取图像的结果直接输出是一个tensor

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)

    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时候,如果需要用额外的包读图像,最好还是用 PIL,因为pytorch源码里就是用到了 PIL 读取图像。

DataLoader加载PyTorch提供的数据集

# 下载并存放数据集
train_dataset = torchvision.datasets.CIFAR10(root="数据集存放位置",download=True)
# load数据
train_loader = torch.utils.data.DataLoader(dataset=train_dataset)

datasets

datasets 属于 torchvision 中的模块,需要利用datasets中的数据时必须提前将其导入,具体代码如下所示

from torchvision import datasets

datasets 中有的数据集有

  • CelebA
  • CIFAR
  • Cityscapes
  • COCO
  • DatasetFolder
  • EMNIST
  • FakeData
  • Fashion-MNIST
  • Flickr
  • HMDB51
  • ImageFolder
  • ImageNet
  • Kinetics-400
  • KMNIST
  • LSUN
  • MNIST
  • Omniglot
  • PhotoTour
  • Places365
  • QMNIST
  • SBD
  • SBU
  • STL10
  • SVHN
  • UCF101
  • USPS
  • VOC
    这些都继承了torch.utils.data.Dataset这个类,所以这些数据集都可以用torch.utils.data.DataLoader的多线程来进行快速的加载。

ImageFolder 和 ImageNet 的配合使用

# 具体例子 1如下所示:
import torch
import torchvision
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
import torchvision.transforms as transforms

data_transform = transforms.Compose([
        transforms.Resize(299),
        transforms.CenterCrop(299),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ])
train_dataset =torchvision.datasets.ImageFolder(root='ILSVRC2012/train',transform=data_transform)
train_dataset_loader =DataLoader(train_dataset,batch_size=4, shuffle=True,num_workers=4)

train_dataset = torchvision.datasets.ImageFolder(root='ILSVRC2012/val',transform=data_transform)
train_dataset_loader = DataLoader(train_dataset,batch_size=4, shuffle=True,num_workers=4)   
# 具体例子 2 如下所示:
import os
import torch
import numpy as np
import matplotlib.pyplot as plt
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, datasets

data_transform = transforms.Compose([
        transforms.RandomSizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ])
hymenoptera_dataset = datasets.ImageFolder(root='hymenoptera_data/train', # 下载到本地ImageNet的路径
                                           transform=data_transform)
dataset_loader = torch.utils.data.DataLoader(hymenoptera_dataset,
                                             batch_size=4, shuffle=True,
                                             num_workers=4)

models

models 属于 torchvision 中的模块,需要调用时,需预先导入,具体代码如下所示:

# 直接导入models
import torchvision.models

# 导入并用别名
import torchvision.models as models

常用于Classification的模型

alexnet vgg resnet squeezenet densenet inception googlenet shufflenet
You can construct a model with random weights by calling its constructor:


import torchvision.models as models
resnet18 = models.resnet18()
alexnet = models.alexnet()
vgg16 = models.vgg16()
squeezenet = models.squeezenet1_0()
densenet = models.densenet161()
inception = models.inception_v3()
googlenet = models.googlenet()
shufflenet = models.shufflenet_v2_x1_0()
mobilenet_v2 = models.mobilenet_v2()
mobilenet_v3_large = models.mobilenet_v3_large()
mobilenet_v3_small = models.mobilenet_v3_small()
resnext50_32x4d = models.resnext50_32x4d()
wide_resnet50_2 = models.wide_resnet50_2()
mnasnet = models.mnasnet1_0()

ImageNet 1-crop error rates (224x224)


# ImageNet 的均值和方差

normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],

                                                           std=[0.229, 0.224, 0.225])

常用于Semantic Segmentation的模型

  • FCN ResNet50, ResNet101
  • DeepLabV3 ResNet50, ResNet101, MobileNetV3-Large
  • LR-ASPP MobileNetV3-Large

The accuracies of the pre-trained models evaluated on COCO val2017 are as follows

常用于 Object Detection, Instance Segmentation and Person Keypoint Detection 的模型

  • Faster R-CNN
  • Mask R-CNN
  • SSD
  • SSDlite
  • RetinaNet

Here are the summary of the accuracies for the models trained on the instances set of COCO train2017 and evaluated on COCO val2017.

transforms

transforms 属于 torchvision 中的模块,用于对数据进行预处理,主要是图像的处理( 有22个function),可以使用Compose将其链接在一起。

transforms中对于图像的处理

  • 裁剪(Crop)—— 中心裁剪:transforms.CenterCrop 随机裁剪:transforms.RandomCrop 随机长宽比裁剪:transforms.RandomResizedCrop 上下左右中心裁剪:transforms.FiveCrop 上下左右中心裁剪后翻转,transforms.TenCrop
  • 翻转和旋转(Flip and Rotation) ——依概率p水平翻转:transforms.RandomHorizontalFlip(p=0.5) 依概率p垂直翻转:transforms.RandomVerticalFlip(p=0.5) 随机旋转:transforms.RandomRotation
  • 图像变换(resize) ——transforms.Resize 标准化:transforms.Normalize 转为tensor,并归一化至[0-1]:transforms.ToTensor 填充:transforms.Pad 修改亮度、对比度和饱和度:transforms.ColorJitter 转灰度图:transforms.Grayscale 线性变换:
    transforms.LinearTransformation() 仿射变换:transforms.RandomAffine 依概率p转为灰度图:transforms.RandomGrayscale 将数据转换为PILImage:transforms.ToPILImage transforms.Lambda:Apply a user-defined lambda as a transform.
  • 对transforms操作,使数据增强更灵活 transforms.RandomChoice(transforms), 从给定的一系列transforms中选一个进行操作 transforms.RandomApply(transforms, p=0.5),给一个transform加上概率,依概率进行操作 transforms.RandomOrder,将transforms中的操作随机打乱

最常用的处理:CenterCrop、Grayscale、RandomCrop、RandomHorizontalFlip、RandomVerticalFlip、RandomRotation、Normalize、ToTensor

# torchvision.transforms.Compose(transforms)
# Compose的例子 1
transforms.Compose([
     transforms.CenterCrop(10),
     transforms.ToTensor(), 
     ])
# Compose的例子 2
data_transform = transforms.Compose([
        transforms.RandomSizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ])

References

  1. Pytorch构建数据集——torch.utils.data.Dataset()和torch.utils.data.DataLoader()
  2. PyTorch 基础 :数据的加载和预处理
  3. 看pytorch official tutorials的新收获
  4. torch.utils.data
  5. DATASETS & DATALOADERS
  6. LEARN THE BASICS
  7. pytorch Dataset, DataLoader产生自定义的训练数据
  8. PyTorch手把手自定义Dataloader读取数据
  9. TORCHVISION.TRANSFORMS
  10. PyTorch 学习笔记:transforms的二十二个方法(transforms用法非常详细)
  11. PyTorch 模型训练实用教程
### 回答1: 如果你是在问 PyTorch 中的数据集和数据加载器,那么我很愿意为您解答。 PyTorch 是一个开源深度学习框架,其中包含了用于加载和预处理数据的工具。其中最重要的两个组件是数据集 (Dataset) 和数据加载器 (DataLoader)。 数据集是一个 PyTorch 类,它定义了如何读取数据、如何访问数据以及如何将数据转换为张量。您可以使用内置的数据集类,例如 torchvision.datasets 中的 ImageFolder,或者自定义数据集类。 数据加载器是一个 PyTorch 类,它可以从数据集中读取数据并将其批量加载到内存中。数据加载器可以进行并行加载,以提高加载速度,并且可以通过 shuffle 参数来随机打乱数据。 举个例子,如果您有一个图像数据集,您可以使用以下代码来创建数据集和数据加载器: ``` import torch import torchvision # 创建数据集 dataset = torchvision.datasets.ImageFolder(root='path/to/data', transform=transforms.ToTensor()) # 创建数据加载器 dataloader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4) ``` 然后,您可以使用以下代码来读取数据: ``` for inputs, labels in dataloader: # 处理输入数据 ... ``` 希望对您有所帮助! ### 回答2: PyTorch是一种广泛使用的深度学习框架,具有易于使用的API和优秀的性能。其中,DatasetDataLoader是两个非常重要的类,它们可以帮助我们有效地加载和处理数据。 Dataset是一个抽象的概念,用于表示一组数据。我们可以继承它并重写其中的方法,以实现对不同数据集的适配。在初始化时,我们需要传递一个数据集,比如说图片数据集,然后在DataLoader中使用这个数据集,实现数据的准备和加载。在自定义Dataset时,我们需要定义__getitem__和__len__两个方法,分别用于返回数据集中的某个数据和数据总数。 DataLoader是一个非常实用的工具,用于加载数据并把数据变成可迭代的对象,其中包含了批量大小、数据是否随机等设置。我们可以设置num_workers参数,用多个进程来读取数据提高读取数据的速度。通过使用DataLoader,我们可以很方便地迭代整个数据集,可以按批次加载和处理数据。 当我们使用在线学习时,经常需要不断地读取数据并进行训练。在应用中,我们会遇到许多不同的数据集,其中可能包含不同的数据类型,比如图像、音频、文本等。使用DatasetDataLoader类,我们可以轻松处理这些数据,从而使我们的深度学习应用具有更广泛的适用性和扩展性。 总之,DatasetDataLoaderPyTorch中非常重要的类,它们可以帮助我们非常方便地进行数据的处理和加载。无论你想要使用哪种数据集,它们都能够很好地适配。在实际应用中,我们可以灵活地使用这两个类来加载和准备数据并进行训练,从而加快应用的速度并提高深度学习的精度。 ### 回答3: PyTorch是一个流行的深度学习框架,它提供了DatasetDataLoader这两个类来帮助我们更方便地处理数据。 Dataset可以看作是一个数据集,它定义了如何读取数据。官方提供了两种Dataset:TensorDataset和ImageFolder。TensorDataset是用来处理张量数据,而ImageFolder则是用来处理图像数据。如果我们需要使用其他类型的数据,我们可以通过重写Dataset类中的__getitem__和__len__方法来实现。 在实现Dataset之后,我们需要将数据读取到内存中,在模型训练时提供给模型,这时我们就需要使用到DataLoader了。DataLoader可以看作是一个数据加载器,它会自动将Dataset中的数据批量读取到内存中,并且支持数据的分布式加载。 在使用DataLoader时我们可以设置很多参数,比如batch_size表示每个batch的大小,shuffle表示是否打乱数据顺序,num_workers表示使用多少线程读取数据等等。这些参数都可以帮助我们更好地利用硬件资源,提高训练速度和效率。 使用PyTorchDatasetDataLoader可以帮助我们更方便快捷地处理数据,并且让我们可以更专注于模型的设计和训练。但我们也要注意一些细节问题,比如数据读取是否正确、内存使用是否合理等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值