1.数据加载
在pytorch中,数据加载可以通过自定义的数据集对象实现。数据集对象被抽象为Dataset类,实现自定义的数据集需要继承Datase类,并且实现Python的两个魔法方法。
a.**__getitem__**:返回一条数据或者样本。如obj[index]等价于obj.__getitem__(index)。如果定义一个 class Dataset(....):
dataset =Dataset(.....) dataset[0]就是按照索引获取我们实际需要的目标以及目标的类别,拿简单的分类问题进行描述。
b.**__len__**: 返回样本的数量。同理我们调用len(obj)等价于obj.__len__() obj为实际Dataset类的某一个实例。
我们一Kaggle经典的‘猫狗分类而言’,将所有照片放在同一个文件下,并且以文件名的前缀作为其实际的类别。
如----cat.12456.jpg
----dog.12563.jpg
import torch
from torch.utils import data
import numpy as np
import os
from PIL import Image
class DogCat(data.Dataset):
def __init__(self,root):
imgs = os.listdir(root):
"""
这里只是指定所有图片的路径,意思就是
你只要能找到对应的图片以及其标签的位置
就可以,不需要返回真正的标签如0或者1以及
他的图片所代表的矩阵
当调用__getitem__时才会真正的读取我们的图片
"""
self.imgs= [os.path.join(rootimg) for img in imgs]
def __getitem__(self,index):
"""
利用index索引我们上述所说的imgs的路径列表
"""
img_path = self.imgs[index]
label = 1 if 'dog' in img_path.split('/')[-1] else 0
pil_img = Image.open(img_path)
array = np.array(pil_img)
data = torch.from_numpy(array)
return data,label
def __len__(self):
return len(self.imgs)
dataset = DogCat('./data/dogcat/')
img,lambel = dataset[0]
for img,label in dataset:
print(img,label)
上述实现了简单的自己数据集类的定义,具体结合Dataloader实现mini-batch,这个在此处不做叙述。我主要是对Dataset总是存在误区,在此处简单记录一下。
2.数据预处理
问题:
利用上述代码可能会因为图片尺寸不同而返回不同的矩阵,这对于batch训练的神经网络来说不友好?
返回样本的数值比较大[0,255],没有归一化至[0,1]
针对上述问题,transforms模块提供了对PIL Image对象和Tensor对象的常用操作
对PIL Image的常见操作。
Resize:调整图片尺寸
CenterCrop、RandomCrop、RandomSizecrop:剪裁图片
Pad:填充
ToTensor:将PIL Image对象转成Tensor,会自动的将[0,255]归一化到[0,1]
对Tensor的常见操作如下。
Normalize:标准化,即减均值,除以标准差
ToPLIImage:将Tensor转为PIL Image
想实现多种数据处理时利用transforms.Compose([]),类似于nn.Sequential()