PyTorch基础(三)-- 数据处理

        由于深度学习所需的样本量很大,一次加载全部数据运行可能会超出内存容量而无法实现;同时还有批(batch)训练等提高模型表现的策略,需要每次训练读取固定数量的样本送入模型中训练,因此深度学习在数据加载上需要有专门的设计。

        PyTorch数据读入是通过Dataset+DataLoader的方式完成的,Dataset定义好数据的格式和数据变换形式,DataLoader用iterative的方式不断读入批次数据。

        本节内容主要学习自《Python深度学习基于PyTorch》第四章——Pytorch数据处理工具箱


1 基础知识

        Pytorch涉及数据处理(数据装载、数据预处理、数据增强等)主要工具包及相互关系如图1所示。

图1 PyTorch主要数据处理工具

        图1 的左边是torch.utils.data工具包,它包括以下三个类:

  • (1)Dataset:是一个抽象类,其它数据集需要继承这个类,并且覆写其中的两个方法(getitemlen)。
  • (2)DataLoader:定义一个新的迭代器,实现批量(batch)读取,打乱数据(shuffle)并提供并行加速等功能。
  • (3)random_split:把数据集随机拆分为给定长度的非重叠新数据集。
  • (4)*sampler:多种采样函数。

        图1中间是Pytorch可视化处理工具(torchvision),Pytorch的一个视觉处理工具包,它包括4个类,各类的主要功能如下:

  • (1)datasets:提供常用的数据集加载,设计上都是继承torch.utils.data.Dataset,主要包括MMIST、CIFAR10/100、ImageNet、COCO等。
  • (2)models:提供深度学习中各种经典的网络结构以及训练好的模型(如果选择pretrained=True),包括AlexNet,
    VGG系列、ResNet系列、Inception系列等。
  • (3)transforms:常用的数据预处理操作,主要包括对Tensor及PIL
    Image对象的操作。
  • (4)utils:含两个函数,一个是make_grid,它能将多张图片拼接在一个网格中;另一个是save_img,它能将Tensor保存成图片。

2 utils.data简介

        我们可以定义自己的Dataset类来实现灵活的数据读取,定义的类需要继承PyTorch自身的Dataset类。主要包含三个函数:

  • __init__: 用于向类中传入外部参数,同时定义样本集
  • __getitem__: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
  • __len__: 用于返回数据集的样本数

        __getitem__一次只能获取一个数据,所以通过torch.utils.data.DataLoader来定义一个新的迭代器,实现batch读取。首先我们来定义一个简单的数据集,然后具体使用Dataset及DataLoader,以便有个直观认识。

(1) 导入需要的模块

import torch
from torch.utils.data import Dataset
import numpy as np

(2)定义获取数据集的类
        该类继承基类Dataset,自定义一个数据集及对应标签。

class TestDataset(Dataset): # 继承Dataset
    def __init__(self):
        self.data = np.asarray([[1, 2], [3, 4], [2, 1], [3, 4], [4, 5]])    # 一些由2维向量表示的数据集
        self.label = np.asarray([0, 1, 0, 1, 2])     # 这是数据集对应的标签

    def __getitem__(self, index):
        inputs = torch.from_numpy(self.data[index])   # 把numpy转换为Tensor
        targets = torch.tensor(self.label[index])
        return inputs, targets
    
    def __len__(self):
        return len(self.data)

(3)获取数据集中数据

Test = TestDataset()
print(Test[2])
print(Test.__len__())
# 输出:
# (tensor([2, 1]), tensor(0))
# 5

        以上数据以tuple返回,每次只返回一个样本。实际上,Dateset只负责数据的抽取,一次调用__getitem__只返回一个样本。如果希望批量处理(batch),同时还要进行shuffle和并行加速等操作,可选择DataLoader。的格式为:

DataLoader(
    dataset,             # dataset: 加载的数据集;
    batch_size=1,        # batch_size: 批大小;
    shuffle=False,       # shuffle:是否将数据打乱;
    sampler=None,        # sampler:样本抽样
    batch_sampler=None,  
    num_workers=0,       # num_workers:使用多进程加载的进程数,0代表不使用多进程;
    collate_fn=,         # collate_fn:如何将多个样本数据拼接成一个batch,一般使用默认的拼接方式即可;
    pin_memory=False,    # pin_memory:是否将数据保存在pin memory区,pin memory中的数据转到GPU会快一些;
    drop_last=False,     # drop_last:dataset 中的数据个数可能不是 batch_size的整数倍,drop_last为True会将多出来不足一个batch的数据丢弃。
    timeout=0,
    worker_init_fn=None,
)

        对于DataLoader(dataset, batch_size=2, shuffle=True)的理解,可以参考下图:

test_loader = DataLoader(Test, batch_size=2, shuffle=False, num_workers=2)
for i, train_data in enumerate(test_loader):
    print('i: ', i)
    data, label = train_data
    print('data: ', data)
    print('label: ', label)

        运行结果为:

i: 0
data: tensor([[1, 2],
[3, 4]])
label: tensor([0, 1])
i: 1
data: tensor([[2, 1],
[3, 4]])
label: tensor([0, 1])
i: 2
data: tensor([[4, 5]])
label: tensor([2])

        从这个结果可以看出,这是批量读取。我们可以像使用迭代器一样使用它,如对它进行循环操作。不过它不是迭代器,我们可以通过iter命令转换为迭代器。

dataiter = iter(test_loader)
imgs, labels = next(dataiter)

        一般用data.Dataset处理同一个目录下的数据。如果数据在不同目录下,不同目录代表不同类别(这种情况比较普遍),使用data.Dataset来处理就不很方便。不过,可以使用Pytorch另一种可视化数据处理工具(即torchvision)就非常方便,不但可以自动获取标签,还提供很多数据预处理、数据增强等转换函数。


3 torchvision简介

        torchvision有4个功能模块,model、datasets、transforms和utils。本节我们将主要介绍如何使用datasets的ImageFolder处理自定义数据集,如何使用transforms对源数据进行预处理、增强等。下面我们重点介绍transforms及ImageFolder。

3.1 transforms

        transforms提供了对PIL Image对象和Tensor对象的常用操作。
(1)对PIL Image的常见操作如下:

  • Scale/Resize: 调整尺寸,长宽比保持不变;
  • CenterCrop、RandomCrop、RandomSizedCrop:裁剪图片,CenterCrop和RandomCrop在crop时是固定size,RandomResizedCrop则是random size的crop;
  • Pad: 填充;
  • ToTensor: 把一个取值范围是[0,255]的PIL.Image 转换成 Tensor。形状为(H,W,C)的numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]的torch.FloatTensor。
  • RandomHorizontalFlip:图像随机水平翻转,翻转概率为0.5;
  • RandomVerticalFlip: 图像随机垂直翻转;
  • ColorJitter: 修改亮度、对比度和饱和度。
    (2)对Tensor的常见操作如下:
  • Normalize: 标准化,即减均值,除以标准差;
  • ToPILImage:将Tensor转为PIL Image。

        如果要对数据集进行多个操作,可通过Compose将这些操作像管道一样拼接起来,类似于nn.Sequential。以下为示例代码

13
transforms.Compose([
    # 将给定的 PIL.Image 进行中心切割,得到给定的 size,
    # size 可以是 tuple,(target_height, target_width)。
    # size 也可以是一个 Integer,在这种情况下,切出来的图片形状是正方形。            
    transforms.CenterCrop(10),
    # 切割中心点的位置随机选取
    transforms.RandomCrop(20, padding=0),
    # 把一个取值范围是 [0, 255] 的 PIL.Image 或者 shape 为 (H, W, C) 的 numpy.ndarray,
    # 转换为形状为 (C, H, W),取值范围是 [0, 1] 的 torch.FloatTensor
    transforms.ToTensor(),
    # 规范化到[-1,1]
    transforms.Normalize(mean = (0.5, 0.5, 0.5), std = (0.5, 0.5, 0.5))
])

3.2 ImageFolder

        当文件依据标签处于不同文件下时,如:
─── data
├── Cat
│ ├── 001.jpg
│ └── 002.jpg
├── Dog
│ ├── 001.jpg
│ └── 002.jpg

        我们可以利用 torchvision.datasets.ImageFolder 来直接构造出 dataset,代码如下:

from torchvision import transforms, datasets
train_data = datasets.ImageFolder(train_path, transform=data_transform)
train_loader = DataLoader(train_data)
val_data = datasets.ImageFolder(val_path, transform=data_transform)

        ImageFolder 会将目录中的文件夹名自动转化成序列,那么DataLoader载入时,标签自动就是整数序列了。


4 案例分析

4.1 在线下载

        直接输入以下代码即可:

from torchvision.datasets import mnist

# 下载数据并对数据预处理
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5,], [0.5,])])
train_dataset = mnist.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = mnist.MNIST(root='./data', train=False, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)

        train=True 代表我们读入的数据作为训练集(如果为true则从training.pt创建数据集,否则从test.pt创建数据集)。download=True则是当我们的根目录(root)下没有数据集时,便自动下载。

4.2 本地导入MNIST数据集

        首先需要自定义数据类来继承和重写Dataset抽象类。

import gzip
import os
from random import shuffle
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms

class MnistDataset(Dataset):
    def __init__(self, folder, data_name, label_name, transform=None):
        (train_set, train_labels) = load_data(folder, data_name, label_name)
        self.train_set = train_set
        self.train_labels = train_labels
        self.transform = transform

    def __getitem__(self, index):
        img, target = self.train_set[index], int(self.train_labels[index])
        if self.transform is not None:
            img = self.transform(img)
        return img, target
    
    def __len__(self):
        return len(self.train_set)

def load_data(data_folder, data_name, label_name):
    with gzip.open(os.path.join(data_folder, label_name), 'rb') as labpath:
        y_train = np.frombuffer(labpath.read(), np.int8, offset=8)
    with gzip.open(os.path.join(data_folder, data_name), 'rb') as imgpath:
        x_train = np.frombuffer(imgpath.read(), np.int8, offset=16).reshape(len(y_train), 28, 28)
    return x_train, y_train

transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5,], [0.5,])])
train_dataset = MnistDataset('./data/MNIST/raw', 'train-images-idx3-ubyte.gz', 'train-labels-idx1-ubyte.gz', transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=64)

        至于offset为什么是8和16,可以看到官方对该数据集的介绍,offset的0000-0003是 magic number,所以跳过不读,offset的0004-0007是items数目。


参考

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: pytorch-multi-label-classifier-master是一个基于PyTorch的多标签分类器项目。该项目旨在使用PyTorch框架构建一个能够对具有多个标签的数据样本进行分类的模型。 PyTorch是一个流行的深度学习框架,能够实现多种深度学习模型的构建与训练。它提供了丰富的工具和函数,简化了模型的复杂性,并提供了高效的计算能力。 在这个项目中,multi-label指的是数据样本可以被分为多个标签。与传统的单标签分类不同,每个样本可以被分为多个类别,这增加了分类问题的复杂性。模型需要学习如何给每个样本分配正确的标签。 pytorch-multi-label-classifier-master项目提供了一个设置多标签分类模型的基础架构。它包含了数据处理、模型构建、训练和评估等步骤。用户可以根据自己的数据集和需求,对该项目进行定制。 通过使用pytorch-multi-label-classifier-master项目,用户可以快速搭建一个多标签分类器,用于解决具有多个标签的数据分类问题。同时,该项目还提供了一些示例数据和模型,帮助用户更好地理解和使用多标签分类技术。 总而言之,pytorch-multi-label-classifier-master是一个基于PyTorch框架用于多标签分类的项目,为用户提供了一个简单且灵活的搭建多标签分类器的框架,方便用户解决多标签分类问题。 ### 回答2: pytorch-multi-label-classifier-master是一个基于PyTorch的多标签分类器项目。它提供了一种使用神经网络模型来处理多标签分类任务的解决方案。 该项目的主要目标是通过深度学习技术来提高多标签分类问题的准确度。它使用PyTorch作为深度学习框架,该框架提供了丰富的工具和功能来构建和训练神经网络模型。 在pytorch-multi-label-classifier-master中,你可以找到许多工具和函数来进行数据处理、模型构建、训练和评估。它支持常见的多标签分类算法,如卷积神经网络(CNN)和递归神经网络(RNN)。你可以根据自己的需求选择合适的模型,并通过简单的配置来进行训练。 该项目还提供了一些示例数据集和预训练模型,以帮助你更快地开始。你可以使用这些数据集来测试和调试你的模型,或者使用预训练模型来进行迁移学习。 pytorch-multi-label-classifier-master还支持一些常见的性能评估指标,如准确率、精确率、召回率和F1值。你可以使用这些指标来评估你的模型在多标签分类任务上的性能。 总的来说,pytorch-multi-label-classifier-master是一个方便易用的项目,旨在帮助你构建和训练用于多标签分类的深度学习模型。它提供了丰富的功能和工具,使你能够快速搭建一个准确度较高的多标签分类器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

长路漫漫2021

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

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

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

打赏作者

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

抵扣说明:

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

余额充值