pytorch学习教程之⾃定义数据集
⾃定义数据集
在训练深度学习模型之前,样本集的制作⾮常重要。在pytorch中,提供了⼀些接⼝和类,⽅便我们定义⾃⼰的数据集合,下⾯完整的试验⾃定义样本集的整个流程。
开发环境
Ubuntu 18.04
pytorch 1.0
pycharm
实验⽬的
1. 掌握pytorch中数据集相关的API接⼝和类
2. 熟悉数据集制作的整个流程
实验过程
1.收集图像样本
以简单的猫狗⼆分类为例,可以在⽹上下载⼀些猫狗图⽚。创建以下⽬录:
data-------------根⽬录
data/test-------测试集
data/train------训练集
data/val--------验证集
在test/train/val之下在校分别创建2个⽂件夹,dog, cat
cat, dog⽂件夹下分别存放2类图像:
标签
种类标签
cat0
dog1
之后写⼀个简单的python脚本,⽣成txt⽂件,⽤于指明每个图像和标签的对应关系。
格式: /cat/1.jpg 0 \n dog/1.jpg 1 \n .....
如图:
⾄此,样本集的收集以及简单归类完成,下⾯将开始采⽤pytorch的数据集相关API和类。
2. 使⽤pytorch相关类,API对数据集进⾏封装
2.1 pytorch中数据集相关的类,接⼝
pytorch中数据集相关的类位于torch.utils.data package中。
本次实验,主要使⽤以下类:
torch.utils.data.Dataset
torch.utils.data.DataLoader
Dataset类的使⽤:所有的类都应该是此类的⼦类(也就是说应该继承该类)。所有的⼦类都要重写(override) __len()__,
__getitem()__ 这两个⽅法。
⽅法作⽤
__len()__此⽅法应该提供数据集的⼤⼩(容量)
__getitem()__此⽅法应该提供⽀持下标索⽅式引访问数据集
这⾥和Java抽象类很相似,在抽象类abstract class中,⼀般会定义⼀些抽象⽅法abstract method,抽象⽅法:只有⽅法名没有⽅法的具体实现。如果⼀个⼦类继承于该抽象类,要重写(overrode)⽗类的抽象⽅法。
DataLoader类的使⽤:
2.2 实现
使⽤到的python package
python package⽬的
numpy矩阵操作,对图像进⾏转置
skimage图像处理,图像I/O,图像变换
matplotlib图像的显⽰,可视化
os⼀些⽂件查操作
torch pytorch
torvision pytorch
源码
导⼊python包
import numpy as np
from skimage import io
from skimage import transform
import matplotlib.pyplot as plt
import os
import torch
import torchvision
from torch.utils.data import Dataset, DataLoader
ansforms import transforms
from torchvision.utils import make_grid
第⼀步:
定义⼀个⼦类,继承Dataset类,重写 __len()__, __getitem()__ ⽅法。
细节:
1.数据集中⼀个⼀样的表⽰:采⽤字典的形式sample = {'image': image, 'label': label}。
2.图像的读取:采⽤skimage.io进⾏读取,读取之后的结果为numpy.ndarray形式。
3.图像变换:transform参数
# step1: 定义MyDataset类,继承Dataset, 重写抽象⽅法:__len()__, __getitem()__
class MyDataset(Dataset):
def __init__(self, root_dir, names_file, transform=None):
<_dir = root_dir
self.names_file = names_file
self.size = 0
self.names_list = []
if not os.path.isfile(self.names_file):
print(self.names_file + 'does not exist!')
file = open(self.names_file)
for f in file:
self.names_list.append(f)
self.size += 1
def __len__(self):
return self.size
def __getitem__(self, idx):
image_path = _dir + self.names_list[idx].split(' ')[0]
if not os.path.isfile(image_path):
print(image_path + 'does not exist!')
return None
image = io.imread(image_path) # use skitimage
label = int(self.names_list[idx].split(' ')[1])
sample = {'image': image, 'label': label}
ansform:
sample = ansform(sample)
return sample
第⼆步
实例化⼀个对象,并读取和显⽰数据集
train_dataset = MyDataset(root_dir='./data/train',
names_file='./data/',
transform=None)
plt.figure()
for (cnt,i) in enumerate(train_dataset):
image = i['image']
label = i['label']
ax = plt.subplot(4, 4, cnt+1)
ax.axis('off')
ax.imshow(image)
ax.set_title('label {}'.format(label))
plt.pause(0.001)
if cnt == 15:
break
只显⽰了部分数据,前部分全是cat
第三步(可选 optional)
对数据集进⾏变换:⼀般收集到的图像⼤⼩尺⼨,亮度等存在差异,变换的⽬的就是使得数据归⼀化。另⼀⽅⾯,可以通过变换进⾏数据增加data argument
关于pytorch中的变换transforms,请参考该系列之前的⽂章
由于数据集中样本采⽤字典dicts形式表⽰。因此不能直接调⽤ansofrms中的⽅法。
本实验只进⾏尺⼨归⼀化Resize, 数据类型变换ToTensor操作。
Resize
numpy官方教程# # 变换Resize
class Resize(object):
def __init__(self, output_size: tuple):
self.output_size = output_size
def __call__(self, sample):
# 图像
image = sample['image']
# 使⽤ansform对图像进⾏缩放
image_new = size(image, self.output_size)
return {'image': image_new, 'label': sample['label']}
ToTensor
# # 变换ToTensor
class ToTensor(object):
def __call__(self, sample):
image = sample['image']
image_new = np.transpose(image, (2, 0, 1))
return {'image': torch.from_numpy(image_new),
'label': sample['label']}
第四步: 对整个数据集应⽤变换
细节: transformers.Compose() 将不同的⼏个组合起来。先进⾏Resize, 再进⾏ToTensor
# 对原始的训练数据集进⾏变换
transformed_trainset = MyDataset(root_dir='./data/train',
names_file='./data/',
transform=transforms.Compose(
[Resize((224,224)),
ToTensor()]
))
第五步:使⽤DataLoader进⾏包装
为何要使⽤DataLoader?
①深度学习的输⼊是mini_batch形式
②样本加载时候可能需要随机打乱顺序,shuffle操作
③样本加载需要采⽤多线程
pytorch提供的DataLoader封装了上述的功能,这样使⽤起来更⽅便。
# 使⽤DataLoader可以利⽤多线程,batch,shuffle等
trainset_dataloader = DataLoader(dataset=transformed_trainset,
batch_size=4,
shuffle=True,
num_workers=4)
可视化:
def show_images_batch(sample_batched):
images_batch, labels_batch = \
sample_batched['image'], sample_batched['label']
grid = make_grid(images_batch)
plt.imshow(grid.numpy().transpose(1, 2, 0))
# sample_batch: Tensor , NxCxHxW
plt.figure()
for i_batch, sample_batch in enumerate(trainset_dataloader):
show_images_batch(sample_batch)
plt.axis('off')
plt.ioff()
plt.show()
plt.show()
通过DataLoader包装之后,样本以min_batch形式输出,⽽且进⾏了随机打乱顺序。
⾄此,⾃定义数据集的完整流程已实现,test, val集只需要改路径即可。
补充
更简单的⽅法
上述继承Dataset, 重写 __len()__, __getitem() 是通⽤的⽅法,过程相对繁琐。对于简单的分类数据集,pytorch中提供了更简便的⽅式——ImageFolder。
如果每种类别的样本放在各⾃的⽂件夹中,则可以直接使⽤ImageFolder。
仍然以cat, dog ⼆分类数据集为例:
⽂件结构:
Code
import torch
from torch.utils.data import DataLoader
from torchvision import transforms, datasets
import matplotlib.pyplot as plt
import numpy as np
# /tutorials/beginner/data_loading_tutorial.html
# data_transform = transforms.Compose([
# transforms.RandomResizedCrop(224),
# transforms.RandomHorizontalFlip(),
# transforms.ToTensor(),
# transforms.Normalize(mean=[0.485, 0.456, 0.406],
# std=[0.229, 0.224, 0.225])
# ])
data_transform = transforms.Compose([
transforms.Resize((224,224)),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
])
train_dataset = datasets.ImageFolder(root='./data/train',transform=data_transform)
train_dataloader = DataLoader(dataset=train_dataset,
batch_size=4,
shuffle=True,
num_workers=4)
def show_batch_images(sample_batch):
labels_batch = sample_batch[1]
images_batch = sample_batch[0]
for i in range(4):
label_ = labels_batch[i].item()
image_ = np.transpose(images_batch[i], (1, 2, 0))
ax = plt.subplot(1, 4, i + 1)
ax.imshow(image_)
ax.set_title(str(label_))
ax.axis('off')
plt.pause(0.01)
plt.figure()
for i_batch, sample_batch in enumerate(train_dataloader):
show_batch_images(sample_batch)
plt.show()
由于 train ⽬录下只有2个⽂件夹,分别为cat, dog, 因此ImageFolder安装顺序对cat使⽤标签0, dog使⽤标签1。
End
参考:
到此这篇关于pytorch学习教程之⾃定义数据集的⽂章就介绍到这了,更多相关pytorch⾃定义数据集内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论