提供做网站公司,php网站说明,百度百家号,做模型的网站PyTorch系列 (二): pytorch数据读取
PyTorch 1: How to use data in pytorch
Posted by WangW on February 1, 2019
参考#xff1a;
PyTorch documentationPyTorch 码源
本文首先介绍了有关预处理包的源码#xff0c;接着介绍了在数据处理中的具体应用#xff1b;
1 P…PyTorch系列 (二): pytorch数据读取
PyTorch 1: How to use data in pytorch
Posted by WangW on February 1, 2019
参考
PyTorch documentationPyTorch 码源
本文首先介绍了有关预处理包的源码接着介绍了在数据处理中的具体应用
1 PyTorch数据预处理以及源码分析 (torch.utils.data)
torch.utils.data脚本码源
1.1 Dataset
Dataset 1class torch.utils.data.Dataset表示Dataset的抽象类。所有其他数据集都应该进行子类化。 所有子类应该override__len__和__getitem__前者提供了数据集的大小后者支持整数索引范围从0到len(self)。 1
2
3
4
5
6
7
8
9
10
11
12class Dataset(object):# 强制所有的子类override getitem和len两个函数否则就抛出错误# 输入数据索引输出为索引指向的数据以及标签def __getitem__(self, index):raise NotImplementedError# 输出数据的长度def __len__(self):raise NotImplementedErrordef __add__(self, other):return ConcatDataset([self, other])TensorDataset 1class torch.utils.data.TensorDataset(*tensors)Dataset的子类。包装tensors数据集输入输出都是元组 通过沿着第一个维度索引一个张量来回复每个样本。 个人感觉比较适用于数字类型的数据集比如线性回归等。 1
2
3
4
5
6
7
8
9
10class TensorDataset(Dataset):def __init__(self, *tensor):assert all(tensors[0].size(0) tensor.size(0) for tensor in tensors)self.tensors tensorsdef __getitem__(self, index):return tuple(tensor[index] for tensor in tensorsdef __len__(self):return self.tensors[0].size(0)ConcatDateset 1class torch.utils.data.ConcatDateset(datasets)连接多个数据集。 目的组合不同的数据集可能是大规模数据集因为连续操作是随意连接的。 datasets的参数要连接的数据集列表 datasets的样式iterable 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class ConcatDataset(Dataset):staticmethoddef cumsum(sequence):# sequence是一个列表e.g. [[1,2,3], [a,b], [4,h]]# return 一个数据大小列表[3, 5, 7], 明显看的出来包含数据多少第一个代表第一个数据的大小第二个代表第一个第二数据的大小最后代表所有的数据大学...def __getitem__(self, idx):# 主要是这个函数通过bisect的类实现了任意索引数据的输出dataset_idx bisect.bisect_right(self.cumulative_size, idx)if dataset_idx 0:sample_idx idxelse:sample_idx idx - self.cumulative_sizes[dataset_idx -1]return self.datasets[dataset_idx][sample_idx]...Subset 1class torch.utils.data.Subset(dataset, indices)选取特殊索引下的数据子集 dataset数据集 indices想要选取的数据的索引
random_split 1class torch.utils.data.random_split(dataset, lengths):随机不重复分割数据集 dataset要被分割的数据集 lengths长度列表e.g. [7, 3] 保证73len(dataset)
1.2 DataLoader
DataLoader 1class torch.utils.data.DataLoader(dataset, batch_size1, shuffleFalse, samplerNone, batch_samplerNone, num_workers0, collate_fnfunction default_collate, pin_memoryFalse, drop_lastFalse, timeout0, worker_init_fnNone)数据加载器。 组合数据集和采样器并在数据集上提供单进程或多进程迭代器。 参数
dataset (Dataset) - 从中加载数据的数据集。batch_size (int, optional) - 批训练的数据个数。shuffle (bool, optional) - 是否打乱数据集一般打乱较好。sampler (Sampler, optional) - 定义从数据集中提取样本的策略。如果指定则忽略shuffle参数。batch_sampler (Sample, optional) - 和sampler类似返回批中的索引。num_workers (int, optional) - 用于数据加载的子进程数。collate_fn (callable, optional) - 合并样本列表以形成小批量。pin_memory (bool, optional) - 如果为True数据加载器在返回去将张量复制到CUDA固定内存中。drop_last (bool, optional) - 如果数据集大小不能被batch_size整除 设置为True可以删除最后一个不完整的批处理。timeout (numeric, optional) - 正数收集数据的超时值。worker_init_fn (callabel, optional) - If not None, this will be called on each worker subprocess with the worker id (an int in [0, num_workers - 1]) as input, after seeding and before data loading. (default: None)
特别重要DataLoader中是不断调用DataLoaderIter
DataLoaderIter 1class _DataLoaderIter(loader)从DataLoader’s数据中迭代一次。其上面DataLoader功能都在这里 插个眼有空在分析这个
1.3 sampler
Sampler 1class torch.utils.data.sampler.Sampler(data_source)所有采样器的基础类 每个采样器子类必须提供一个__iter__方法提供一种迭代数据集元素的索引的方法以及返回迭代器长度__len__方法。
class Sampler(object):def __init__(self, data_source):passdef __iter__(self):raise NotImplementedErrordef __len__(self):raise NotImplementedErrorSequentialSampler 1class torch.utils.data.SequentialSampler(data_source)样本元素顺序排列始终以相同的顺序。 参数-data_source (Dataset) - 采样的数据
RandomSampler 1class torch.utils.data.RandomSampler(data_source, replacementFalse, num_samplesNone)样本随机排列如果没有Replacement将会从打乱的数据采样否则。。 参数
data_source (Dataset) - 采样数据num_samples (int) - 采样数据大小默认是全部。replacement (bool) - 是否放回
SubsetRandomSampler 1class torch.utils.data.SubsetRandomSampler(indices)从给出的索引中随机采样without replacement。 参数
indices (sequence) - 索引序列。
BatchSampler 1class torch.utils.data.BatchSampler(sampler, batch_size, drop_last)将采样封装到批处理索引。 参数
sampler (sampler) - 基本采样batch_size (int) - 批大小drop_last (bool) - 是否删掉最后的批次
weightedRandomSampler 1class torch.utils.data.WeightedRandomSampler(weights, num_samples, replacementTrue)样本元素来自[0,…,len(weights)-1] 给定概率权重。 参数
weights (list) - 权重列表。不需要加起来为1num_samplers (int) - 要采样数目replacement (bool) -
1.4 Distributed
DistributedSampler 1class torch.utils.data.distributed.DistributedSampler(dataset, num_replicasNone, rankNone)????没读呢
1.5 其它链接
PyTorch源码解读之torch.utils.data.DataLoader
2 torchvision
计算机视觉用到的库文档以及码源如下
torchvision documentationtorchvision 其库主要包含一下内容
torchvision.datasets MNISTFashion-MNISTEMNISTCOCOLSUNImageFolderDatasetFolderImagenet-12CIFARSTL10SVHNPhoto TourSBUFlickrVOCtorchvision.models AlexnetVGGResNetSqueezeNetDenseNetInception v3torchvision.transforms Transforms on PIL ImageTransfroms on torch.* TensorConversion TransformsGeneric TransformsFunctional Transformstorchvision.utils
3 应用
3.1 init
具有一下图像数据如下表示
train normal 1.png2.png…8000.pngtumor 1.png2.png…8000.pngvalidation normal 1.pngtumor 1.png
希望能够训练模型使得能够识别tumor, normal两类将tumor–1, normal–0。
3.2 数据读取
在PyTorch中数据的读取借口需要经过Dataset和DatasetLoader (DatasetloaderIter)。下面就此分别介绍。
Dataset
首先导入必要的包。
import osimport numpy as np
from torch.utils.data import Dataset
from PIL import Imagenp.random.seed(0)其次定义MyDataset类为了代码整洁精简将不必要的操作全删e.g. 图像剪切等。
class MyDataset(Dataset):def __init__(self, root, size229, ):Initialize the data producerself._root rootself._size sizeself._num_image len(os.listdir(root))self._img_name os.listdir(root)def __len__(self):return self._num_imagedef __getitem__(self, index):img Image.open(os.path.join(self._root, self._img_name[index]))# PIF image: H × W × C# torch image: C × H × Wimg np.array(img, dtype-np.float32).transpose((2, 0, 1))return imgDataLoader
将MyDataset封装到loader器中。
from torch.utils.data import DataLoader# 实例化MyData
dataset_tumor_train MyDataset(root/img/train/tumor/)
dataset_normal_train MyDataset(root/img/train/normal/)
dataset_tumor_validation MyDataset(root/img/validation/tumor/)
dataset_normal_validation MyDataset(root/img/validation/normal/)# 封装到loader
dataloader_tumor_train DataLoader(dataset_tumor_train, batch_size10)
dataloader_normal_train DataLoader(dataset_normal_train, batch_size10)
dataloader_tumor_validation DataLoader(dataset_tumor_validation, batch_size10)
dataloader_normal_validation DataLoader(dataset_normal_validation, batch_size10) 3.3 train_epoch
简单将数据流接口与训练连接起来
def train_epoch(model, loss_fn, optimizer, dataloader_tumor, dataloader_normal):model.train()# 由于tumor图像和normal图像一样多所以将tumornormal连接起来stepslen(tumor_loader)len(normal_loader)steps len(dataloader_tumor)batch_size dataloader_tumor.batch_sizedataiter_tumor iter(dataloader_tumor)dataiter_normal iter(dataloader_normal)for step in range(steps):data_tumor next(dataiter_tumor)target_tumor [1, 1,..,1] # 和data_tumor长度相同的tensordata_tumor Variable(data_tumor.cuda(asyncTrue))target_tumor Variable(target_tumor.cuda(asyncTrue))data_normal next(dataiter_normal)target_normal [0, 0,..,0] # data_normal Variable(data_normal.cuda(asyncTrue))target_normal Variable(target_normal.cuda(asyncTrue))idx_rand Variable(torch.randperm(batch_size*2).cuda(asyncTrue))data torch.cat([data_tumor, data_normal])[idx_rand]target torch.cat([target_tumor, target_normal])[idx_rand]output model(data)loss loss_fn(output, target)optimizer.zero_grad()loss.backward()optimizer.step()
任何程序错误以及技术疑问或需要解答的请添加