数据预处理
概述
torchvision.transform是一个包含了常用图像变化方法的工具包. 该工具包主要用于图像的预处理,数据增强等工作之中. 本节我们将详细介绍torchvision.transforms中常用的数据处理函数
知识点:
- 预处理的批操作
- 葡萄酒数据的预处理
- 图像数据的预处理
数据的预处理
Compose
首先让我们先来学习torchvision.transforms.Compose(), 它的参数是一个由多个transforms包中的方法组成的列表. 简单的说, 该函数的主要目的就是将所有的预处理操作进行打包, 当有数据来时, 我们只需要将数据传入该函数中,就能一次性对数据进行所有预处理操作
import torchimport torchvisionclass ToTensor:def __call__(self,x):return torch.from_numpy(x)class MulTransform:def __call__(self,x):x*=2return xcomposed = torchvision.transforms.Compose([ToTensor(),MulTransform()])print(composed)
上面我们定义了一个预处理的集合器, 我们只需要将数据传入composed中,PyTorch就会自动对数据进行ToTensor()和MulTransform()操作.
import numpy as npdata = np.array([1,2,3])composed(data)
从结果可以看出, 尽管我们的数据需要进行很多次的预处理, 但是我们只需要将这些预处理全部放入Compose中进行打包,就能形成一个数据预处理结合.
当我们需要处理某些数据时, 只需要简单的将数据传入这个集合即可.
接下来, 我们以葡萄酒的数据预处理为例,修改上一个实验的WineDataset类, 使其能够输出归一化后的Tensor数据集.
葡萄酒数据的预处理
首先, 还是让我们先来定义数据集合:
# 我们自己封装一个Dataset类from torch.utils.data import Datasetimport pandas as pdclass WineDataset(Dataset):# 建立一个数据集合继承Datasetdef __init__(self,transform):# 加载wine.csv中的数据xy = pd.read_csv("./wine.csv")# 采样数据self.samples_num = xy.shape[0]# 将pandas类型数据转成tensor类型self.datas = xy.values[:,1:]self.labels = xy.values[:,0].reshape(-1,1)# 数据的预处理self.transform = transformdef __getitem__(self,index):sample = self.datas[index],self.labels[index]if self.transform:return self.transform(sample)return sampledef __len__(self):return self.samples_num
可以看出WineDataset类中的代码和上一个案例大致相同, 我们只是多加了一个transform变量,即数据预处理操作的集合. 该变量并没有在WineDataset类中被定义,只是作为一个参数被传入.
这样做有一个好处就是, 当我们需要在原来基础上添加新的预处理操作时, 我们只需要在模型外重新定义transform变量即可. 无需修改原来类中的代码.
接下来, 就让我们来定义预处理操作了.
首先,让我们来定义数据归一化操作,我们这里使用最大最小归一化
# 为了便于计算,我们将数据进行归一化操作class Normalization:def __call__(self,sample):inputs,targets = sampleamin,amax = inputs.min(),inputs.max()inputs = (inputs - amin)/(amax - amin)return inputs,targets# 测试代码a = 10 * np.random.random((5,5))print(a)# 前4列表示数据,最后1列表示标签asample = [a[:,0:4],a[:,4]]Normalization()(asample)
接下来, 让我们来定义数据的转化操作,即将原数据类型转为Tensor:
class ToTensor:def __call__(self, sample):inputs, targets = samplereturn torch.from_numpy(inputs),torch.from_numpy(targets)# 测试代码a = 10 * np.random.random((5,5))# 测试数据,前4列表示特征, 最后一列表示标签data = [a[:,0:4],a[:,4]]ToTensor()(data)
最后, 让我们使用这两个预处理的操作, 来处理葡萄酒数据.
我们无需修改上面的代码, 只需将其封装到Compose中, 再传入即可.
# 最后无需修改上面的代码,我们将其封装到compose中composed = torchvision.transforms.Compose([Normalization(),ToTensor()])# 传入该参数wineData = WineDataset(transform=composed)# 第一条数据features,labels = wineData[0]# 打印输出类型print(type(features),type(labels))
图像的预处理
transform中有很多关于图像的预处理
import torchvision.transforms as transformsfrom PIL import Imageimport matplotlib.pyplot as plt%matplotlib inlineimport cv2 as cvimg = Image.open("bozai.jpg")plt.imshow(img)


裁剪图片
transform = torchvision.transforms.CenterCrop((64,200))new_img = transform(img)plt.imshow(new_img)


# 改变图片的亮度,对比度和饱和度plt.subplot(221)plt.imshow(img)# 随机改变亮度img1 = torchvision.transforms.ColorJitter((0.5,0.6))(img)plt.subplot(222)plt.imshow(img1)# 随机改变对比度img2 = torchvision.transforms.ColorJitter(0,(0.5,0.6))(img)plt.subplot(223)plt.imshow(img2)# 随机改变饱和度img3 = torchvision.transforms.ColorJitter(0,0,(0.5,0.6))(img)plt.subplot(224)plt.imshow(img3)


# 图像的灰度处理plt.subplot(131)plt.imshow(img)img1 = torchvision.transforms.Grayscale(1)(img)plt.subplot(132)plt.imshow(img1,"gray")img2 = torchvision.transforms.Grayscale(3)(img)plt.subplot(133)plt.imshow(img2)


# 给PIL图像进行填充plt.subplot(121)plt.imshow(img)# 四周加边界img1 = torchvision.transforms.Pad(padding=20,fill=(0,255,255),padding_mode="constant")(img)plt.subplot(122).set_title("pad")plt.imshow(img1)


# 保持图像中心不变的仿射变换,,在空余位置补0img1 = torchvision.transforms.RandomAffine(60)(img)plt.subplot(221).set_title("rotate_only")plt.imshow(img1)img2 = torchvision.transforms.RandomAffine(60,translate=(0.3,0.3))(img)plt.subplot(222).set_title("rotate_translate")plt.imshow(img2)img3 = torchvision.transforms.RandomAffine(60,scale=(2.0,2.3))(img)plt.subplot(223).set_title("rotate_scale")plt.imshow(img3)img4 = torchvision.transforms.RandomAffine(60,shear=60)(img)plt.subplot(224).set_title("shear_only")plt.imshow(img4)plt.tight_layout()


# 将原图像进行随机裁剪,裁剪后重新缩放size大小img1 = torchvision.transforms.RandomResizedCrop((128,128),scale=(0.08,1.0),ratio=(0.75,1.33),interpolation=2)(img)plt.imshow(img1)


小结
本节我们阐述了torchvision.transforms的使用方法和torchvision.transforms中内置的处理函数,这些预处理操作是非常重要的, 一系列好的数据预处理操作,可以大大的加快模型收敛速度,提高模型的准确率和鲁棒性/
