Pytorch袖珍手册之四

2021-08-19  本文已影响0人  深思海数_willschang
pytorch pocket reference

第三章 基于Pytorch的深度学习开发

前面章节我们已经了解tensor及其操作,这章主要就是学习如何用Pytorch进行基础深度学习应用开发。
本章主要内容

在后面的篇章中,本书也会提供其它更加复杂模型来阐述一个完整的深度学习结构中各个环节的技巧及意义,如自主化,优化,加速,分布式训练及高效部署方案等等。

本章主要以一个基本的神经网络模型结构展开讨论的,即达到以小见大的作用。

整体流程

虽然每个人所构建的模型结构各不相同,但整个流程却是一样的。即不管是监督学习,非监督学习或是半监督学习,整个流程还都是 训练,测试,部署

overall process

数据预处理(Data Preparation)

Pytorch的一些包,如Torchvision和Torchtext等也都提供了一些不错数据加载处理方法。
torchvison.datasets就提供了很多的子类用于加载一些不错的图片数据(CIFAR-10,MNIST等)。

示例:CIFAR10数据加载及预览

from torchvision.datasets import CIFAR10
from PIL import Image

train_data = CIFAR10(root='./train/', train=True, download=True)
print(train_data)
"""
Dataset CIFAR10
    Number of datapoints: 50000
    Root location: ./train/
    Split: Train
"""
print(len(train_data), train_data.data.shape, train_data.classes, train_data.class_to_idx)
print(train_data[0])
"""
50000 
(50000, 32, 32, 3) 
['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] 
{'airplane': 0, 'automobile': 1, 'bird': 2, 'cat': 3, 'deer': 4, 'dog': 5, 'frog': 6, 'horse': 7, 'ship': 8, 'truck': 9}

(<PIL.Image.Image image mode=RGB size=32x32 at 0x2577B5677F0>, 6)
"""


test_data = CIFAR10(root='./test/', train=False, download=True)
print(test_data)
"""
Dataset CIFAR10
    Number of datapoints: 10000
    Root location: ./test/
    Split: Test
"""
print(len(test_data))
print(test_data.data.shape)
"""
10000
(10000, 32, 32, 3)
"""

查看一下图片数据


plt show

示例:对CIFAR10数据进行一些预处理操作

from torchvision.datasets import CIFAR10
from torchvision import transforms

# 定义一系列transform算子,随机裁剪,水平翻转等
train_transforms = transforms.Compose([
        transforms.RandomCrop(32, padding=4),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(
        mean=(0.4914, 0.4822, 0.4465),
        std=(0.2023, 0.1994, 0.2010)
        )
    ])

# 通过参数tranform指定数据预处理操作
train_data = CIFAR10(root="./train/",
        train=True,
        download=True,
        transform=train_transforms
    )

print(train_data)
"""
Dataset CIFAR10
    Number of datapoints: 50000
    Root location: ./train/
    Split: Train
    StandardTransform
Transform: Compose(
               RandomCrop(size=(32, 32), padding=4)
               RandomHorizontalFlip(p=0.5)
               ToTensor()
               Normalize(mean=(0.4914, 0.4822, 0.4465), std=(0.2023, 0.1994, 0.201))
           )
"""
# torch.Size([3, 32, 32])
print(train_data[0][0].size())

print(train_data[0])
"""
(tensor([[[-2.4291, -2.4291, -2.4291,  ..., -2.4291, -2.4291, -2.4291],
         [-2.4291, -2.4291, -2.4291,  ..., -2.4291, -2.4291, -2.4291],
         [-2.4291, -2.4291, -2.4291,  ..., -2.4291, -2.4291, -2.4291],
         ...,
         [ 1.1959,  0.4981,  0.0522,  ...,  1.1765, -0.1610, -2.4291],
         [ 1.3122,  0.8276,  0.4981,  ..., -0.0253, -1.0527, -2.4291],
         [ 1.4673,  1.1765,  0.9051,  ..., -1.3435, -1.7894, -2.4291]],

        [[-2.4183, -2.4183, -2.4183,  ..., -2.4183, -2.4183, -2.4183],
         [-2.4183, -2.4183, -2.4183,  ..., -2.4183, -2.4183, -2.4183],
         [-2.4183, -2.4183, -2.4183,  ..., -2.4183, -2.4183, -2.4183],
         ...,
         [ 0.1188, -0.4516, -0.8646,  ...,  0.6301, -0.7269, -2.4183],
         [ 0.2564, -0.0189, -0.2352,  ..., -0.5892, -1.4742, -2.4183],
         [ 0.5318,  0.4924,  0.3154,  ..., -1.8479, -2.0446, -2.4183]],

        [[-2.2214, -2.2214, -2.2214,  ..., -2.2214, -2.2214, -2.2214],
         [-2.2214, -2.2214, -2.2214,  ..., -2.2214, -2.2214, -2.2214],
         [-2.2214, -2.2214, -2.2214,  ..., -2.2214, -2.2214, -2.2214],
         ...,
         [-1.7141, -1.7336, -1.5580,  ..., -0.4460, -1.2849, -2.2214],
         [-1.9092, -1.8507, -1.5385,  ..., -1.2654, -1.7141, -2.2214],
         [-1.7922, -1.7531, -1.6751,  ..., -2.0458, -2.0458, -2.2214]]]), 6)
"""

# 对于测试数据同样需要做相应的处理,至少也要将图像数据转换为Tensor形式
test_transforms = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize(
        (0.4914, 0.4822, 0.4465),
        (0.2023, 0.1994, 0.2010))
    ])

test_data = CIFAR10(
        root="./test/",
        train=False,
        transform=test_transforms)

print(test_data)
"""
Dataset CIFAR10
    Number of datapoints: 10000
    Root location: ./test/
    Split: Test
    StandardTransform
Transform: Compose(
               ToTensor()
               Normalize(mean=(0.4914, 0.4822, 0.4465), std=(0.2023, 0.1994, 0.201))
           )
"""

对比预处理前后照片效果图


transform effort

从图中我们可以发现前后数据发生了一些变化,可能对于我们来说看不懂,但经过这样的处理后,模型的预测效率有不错的提升。

%matplotlib inline
import matplotlib.pyplot as plt
from torchvision.datasets import CIFAR10
from torchvision import transforms

# 加载数据,不做任何预处理
train_data_ori = CIFAR10(root='./train/', train=True, download=True)

# 定义一系列transform算子,随机裁剪,水平翻转等
train_transforms = transforms.Compose([
        transforms.RandomCrop(32, padding=4),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(
        mean=(0.4914, 0.4822, 0.4465),
        std=(0.2023, 0.1994, 0.2010)
        )
    ])

# 通过参数tranform指定数据预处理操作
train_data_trans = CIFAR10(root="./train/",
        train=True,
        download=True,
        transform=train_transforms
    )

data_ori, label_ori = train_data_ori[0]
data_trans, label_trans = train_data_trans[0]

# transform前后图片对比
plt.figure(figsize=(8, 8)) 
plt.subplot(1, 2, 1)
plt.imshow(data_ori)
plt.subplot(1, 2, 2)

# 将tensor转换为PIL Image格式
image_trans = transforms.ToPILImage()(data_trans) # 自动转换为0-255
plt.imshow(image_trans)
plt.tight_layout()
plt.show()

同样数据批处理也十分简单的,只要通过torch.utils.data.DataLoader类即可实现。

示例:对训练数据进行批量化处理
下面的例子是有放回的批量化处理,每批次有16个样本进行模型训练计算。经过DataLoader处理过的数据相当于一个迭代器,可以通过next()及iter()方法进行数据获取next(iter(train_loader))

train_loader = torch.utils.data.DataLoader(
      train_data_trans,
      batch_size=16,
      shuffle=True
)

data_batch, labels_batch = next(iter(train_loader))

# 每批次的数据情况,16个 3*32*32
print(data_batch.size())
print(labels_batch.size())
"""
torch.Size([16, 3, 32, 32])
torch.Size([16])
"""

普通应用中数据预处理(General Data Preparation)

torch.utils.data
前面的例子我们知道了图片数据是如何通过torchvision这个包进行加载,转换和批处理。但对于我们实际应用中的数据,我们是要怎么来做这些预处理呢?Pytorch提供了一个内置模块来帮我们完成这些工作,即torch.utils.data。

Pytorch提供了对数据进行映射和迭代类型的数据集类torch.utils.data.Dataset,通过继承其并重写相关函数方法实现数据的加载,处理及返回等预处理操作。

torch.utils.data.DataLoader(
dataset,
batch_size=1,
shuffle=False,
sampler=None,
batch_sampler=None,
num_workers=0,
collate_fn=None,
pin_memory=False,
drop_last=False,
timeout=0,
worker_init_fn=None,
multiprocessing_context=None,
generator=None)

在正常情况下,dataset,batch_size,shuffle和sampler这几个参数比较常用到,其他一些参数主要是在特殊场景下使用,主要还是要根据实际应用来选择。期中num_workers主要是利用cpu的多核技术来并行处理生成数据,提高效率。

If you write your own dataset class, all you need to do is call the built-in DataLoader to generate an iterable for your data. There is no need to create a dataloader class from scratch.

上一篇 下一篇

猜你喜欢

热点阅读