在深度学习中,数据的处理对于神经网络的训练来讲十分重要,良好的数据(包括图像、文本、语音等)处理不只能够加速模型的训练,同时也直接关系到模型的效果。本文以处理图像数据为例,记录一些使用PyTorch进行图像预处理和数据加载的方法。网络
在PyTorch中,数据加载须要自定义数据集类,并用此类来实例化数据对象,实现自定义的数据集须要继承torch.utils.data包中的Dataset类。
在继承Dataset实现本身的类时,须要实现如下两个Python魔法方法:dom
例如,以猫狗大战的二分类数据集为例,其加载过程以下:
工具
import os import torch as t from torch.utils import data from PIL import Image import numpy as np class dogCat(data.Dataset): def __init__(self,root): # root为数据存放目录 imgs = os.listdir(root) #列出当前路径下全部的文件 self.imgs = [os.path.join(root,img) for img in imgs] # 全部图片的路径 #print(self.imgs) """返回一个样本数据""" def __getitem__(self, item): img_path = self.imgs[item] # 第item张图片的路径 #dog 1 cat 0 label = 1 if 'dog' in img_path.split('\\')[-1] else 0 # 获取标签信息 #print(label) pil_img = Image.open(img_path) #读入图片 print(type(pil_img)) array = np.asarray(pil_img) # 转为numpy.array类型 data = t.from_numpy(array) # 转为tensor类型 return data,label #返回图片对应的tensor及其标签 """样本的数量""" def __len__(self): return len(self.imgs) if __name__ == '__main__': dogcat = dogCat('D:\pycode\dogsVScats\data\catvsdog\\train') #数据集对象 data,label = dogcat[0] # 返回第0张图片的信息 print(data.size()) print(label) print(len(dogcat))
对于图像数据来讲,以上的数据加载时不完善的,由于只是将图片读入,而没有进行相关的处理,如每张图片的大小和形状,样本的数值归一化等等。
为了解决这一问题,PyTorch开发了一个视觉工具包torchvision,这个包独立于torch,须要经过pip install torchvision
来单独安装。
torchvision有三个部分组成:学习
from torchvision import models from torch import nn resnet34 = models.resnet34(pretrained=True,num_classes=1000) # 加载预训练模型 resnet34.fc=nn.Linear(512,10) # 修改全链接层为10分类
from torchvision import datasets dataset = datasets.MNIST('data/',download=True,train=False,transform=transform)
除了经常使用数据集外,须要特别注意的是ImageFolder,ImageFolder假设全部的文件按文件夹存放,每一个文件夹下面存储同一类的图片,文件夹的名字为这一类别的名字。这是咱们常常用到的一种数据组织形式。code
# 使用方法: ImageFolder(root,transform=None,target_transform=None,loader=default_loader) # 参数:文件夹路径,对图像作什么样的转换,对标签作什么样的转换,如何加载图片 from torchvision.datasets import ImageFolder dataset = ImageFolder('data\\') print(dataset.class_to_idx) # class_to_idx ,label和id的对应关系,从0开始 print(dataset.imgs) # 数据和标签对应
对PIL Image的操做:Resize、CenterCrop、RandomCrop、RandomsizedCrop、Pad、ToTensor等。orm
对Tensor的操做:Normalize、ToPILImage等。对象
若是要进行多个操做,能够经过transforms.Compose([])将操做拼接起来。可是须要注意的是须要首先构建转换操做,而后再执行转换操做。继承
import os from torch.utils import data from PIL import Image import numpy as np from torchvision import transforms as T transform = T.Compose([T.Resize(224),T.CenterCrop(224),T.ToTensor(),T.Normalize(mean=[.5,.5,.5],std=[.5,.5,.5])]) # 构建转换操做 class dogCat(data.Dataset): def __init__(self,root,transforms): imgs = os.listdir(root) #print(imgs) self.imgs = [os.path.join(root,img) for img in imgs] #print(self.imgs) self.transforms = transforms def __getitem__(self, item): img_path = self.imgs[item] #dog 1 cat 0 label = 1 if 'dog' in img_path.split('\\')[-1] else 0 #print(label) pil_img = Image.open(img_path) if self.transforms: pil_img = self.transforms(pil_img) #执行准换操做 return pil_img,label,item def __len__(self): return len(self.imgs)
经过上述描述,咱们经过自定义数据集类,使用视觉工具包进行图像的转换等操做,最终获得的是一个dataset的数据集对象,使用此对象能够一次返回一个样本。
可是,咱们应该清楚:训练神经网络时,通常采用的是小批量的梯度降低,所以咱们是对一批数据进行处理,也就是一个batch,同时,数据还须要进行打乱(shuffle)和并行加速等。PyTorch提供了DataLoader来实现这些功能。
DataLoader定义以下:进程
DataLoader(dataset,batch_size=1,shuffle=False,sampler=None,num_workers=0,collate_fn=default_collate,pin_memory=False,drop_last=False)
参数含义以下:图片
调用DataLoader获得的结果是一个可迭代的对象,能够和使用迭代器同样使用它。
from torchvision import transforms as T from torch.utils.data import DataLoader transform = T.Compose([T.Resize(224),T.CenterCrop(224),T.ToTensor(),T.Normalize(mean=[.5,.5,.5],std=[.5,.5,.5])]) if __name__ == '__main__': dogcat = dogCat('D:\pycode\dogsVScats\data\catvsdog\\train', transform) data, label, index = dogcat[0] dataloader = DataLoader(dogcat,batch_size=3,shuffle=False,num_workers=0,drop_last=False) for batchDatas,batchLabels in dataloader: train()
本文记录了使用PyTorch进行数据预处理的相关操做流程,重点是掌握Dataset和DataLoader两个类的使用,另外,视觉工具包torchvision的三个模块灵活运用,会对数据处理过程有很好的帮助。