前言:
在torch.utils.data模块中包含一些常用的数据预处理的操作,比如数据的读取、切分、准备等,通过使用这些类,我们可以对高维数组、图像等各种类型的数据进行预处理,以便在深度学习模型中使用。在本文中,我们主要介绍回归模型和分类模型在高维数组和图像数据上的相关预处理与数据准备工作。
一、高维数组:
很多情况下我们需要从文本(csv)文件中读取高位数组数据,这类数据的特征是每个样本都有很多的预测变量(特征)和一个被预测变量(标签) 。特征通常是数值变量或离散变量,标签若是连续的数值则对应回归问题,若离散则对应分类问题。在使用Pytorch建立模型时,我们通常要对数据进行预处理并将它们转化为网络需要的数据形式。下面我们使用Boston数据集和Iris数据集进行回归模型和分类模型的数据准备。
1.回归模型数据准备(boston数据集):
首先我们加载使用的模块,代码如下:
import torch
import torch.utils.data as data
from sklearn.datasets import load_boston,load_iris
import numpy as np
接下来我们读取boston数据集,代码如下:
boston_X,boston_y = load_boston(return_X_y=True)
print("boston_X.dtype:",boston_X.dtype)
print("boston_y.dtype:",boston_y.dtype)
输出boston数据集的特征和标签的数据类型,结果为:
boston_X.dtype: float64
boston_y.dtype: float64
但是在使用Pytorch时我们需要的数据类型是torch的32位float型张量,因此我们需要使用astype()方法将数据集boston_X和boston_y中的64位浮点型数组转化为32位浮点型张量,(其中使用astype()方法先转化为32位float型数据,然后将numpy数组转化为张量)代码如下:
#需要将数据转换成pytorch的float32位格式
#训练集X转化为张量 训练集y转化为张量
train_xt = torch.from_numpy(boston_X.astype(np.float32))
train_yt = torch.from_numpy(boston_y.astype(np.float32))
print("train_xt.dtype:",train_xt.dtype)
print("train_yt.dtype:",train_yt.dtype)
在训练全连接神经网络的时候,我们通常一次使用一个batch的数据进行权重更新,我们可以通过torch.utils.data.DataLoader()函数通过输入的数据集(包含特征和标签)获得一个加载器,在每次迭代的时候使用一个batch的数据,代码如下:
#将训练集转化为张量后 使用TensorDataset将X和Y整理到一起
train_data = data.TensorDataset(train_xt,train_yt)
#定义一个数据加载器 将训练数据集进行批量处理
train_loader = data.DataLoader(
dataset=train_data,#使用的数据集
batch_size=64,
shuffle=True,#每次迭代前打乱样本数据
num_workers=1,#使用两个进程
)
#获得一次加载器的输出内容,检查训练数据集的一个batch样本的维度是否正确
#enumerate返回一个组合的枚举对象
for step,(b_x,b_y) in enumerate(train_loader):
if step>0:
break
print("b_x.shape=",b_x.shape)
print("b_y.shape=",b_y.shape)
print("b_x.dtype=",b_x.dtype)
print("b_y.dtype=",b_x.dtype)
结果如下,从代码中我们首先使用 data.TensorDataset()函数将训练数据train_xt,train_yt整理到一起成为训练数据集train_data,然后使用data.DataLoader()函数定义一个batchsize=64的数据加载器,然后获取加载器一个batch中的数据b_x和b_y的数据类型,可以发现都是pytorch中使用的float32。
2.分类模型数据准备(iris数据集):
对于分类模型数据准备与回归模型有所不同,分类模型数据的被预测变量为离散类别变量,因此在使用pytorch定义网络模型时,默认的预测标签是64位有符号整型数据(回归数据是32位浮点型数据)。
我们首先先读取数据,然后查看数据的特征和标签分别对应的数据类型,代码如下:
#处理分类数据
iris_x,irisy = load_iris(return_X_y=True)
print("iris_x.dtype:",iris_x.dtype)
print("irisy.dtype:",irisy.dtype)
结果如下,说明特征为64位浮点型,标签为32位整型。
iris_x.dtype: float64
irisy.dtype: int32
接下来,我们需要将特征和标签分别转化为32位浮点型和64位有符号整型的张量,代码如下:
#训练集x转化为张量 训练集y转化为张量
train_xt = torch.from_numpy(iris_x.astype(np.float32))
train_yt = torch.from_numpy(irisy.astype(np.int64))
print("train_xt.dtype:",train_xt.dtype)
print("train_yt.dtype:",train_yt.dtype)
结果为:
train_xt.dtype: torch.float32
train_yt.dtype: torch.int64
调整好数据类型后,我们再使用 data.TensorDataset()函数和data.DataLoader()函数定义一个数据加载器,代码如下:
#将训练集转化为张量后 使用tensordataset将X和Y整理到一起
train_data = data.TensorDataset(train_xt,train_yt)
#定义一个数据加载器 将训练数据集批量处理
train_loader = data.DataLoader(
dataset=train_data,
batch_size = 64,
shuffle=True,
num_workers=1,
)
#检查训练数据集的一个样本的维度是否正确
for step,(b_x,b_y) in enumerate(train_loader):
if step > 0:
break
#输出训练图像的尺寸、标签的尺寸、数据类型
print("b_x.shape=",b_x.shape)
print("b_y.shape=",b_y.shape)
print("b_x.dtype=",b_x.dtype)
print("b_y.dtype=",b_y.dtype)
结果如下,可知每个batch使用64个数据样本,且样本的数据类型已正确转化。
b_x.shape= torch.Size([64, 4])
b_y.shape= torch.Size([64])
b_x.dtype= torch.float32
b_y.dtype= torch.int64
二、图像数据:
torchvision中的datasets模块包含多种常用的分类数据集下载和导入函数,可以很方便的导入数据以及验证模型效果,部分数据集如下所示:
torchvision中的transforms模块可以对每张图像进行预处理操作,部分变换操作如下:
接下来,我们使用代码以实际的数据集为例,来展示通过torchvision中的有关模块进行图像数据的两种预处理操作:第一种是从torchvision中的datasets模块中导入数据并进行预处理;第二种是从文件夹中导入图片数据并进行预处理。
我们先导入所需要的模块,代码如下:
import torch
import torch.utils.data as Data
from torchvision.datasets import FashionMNIST
import torchvision.transforms as transforms
from torchvision.datasets import ImageFolder
1.从torchvision中的datasets模块中导入数据并进行预处理:
这里我们以导入FashionMNIST数据集为例,该数据集包含60000张28*28的灰度图片作为训练集,10000张28*28的灰度图片作为测试集,并分为10类数据。
首先,我们使用datasets类中的FashionMNIST函数来导入数据,并在导入数据后使用Data.DataLoader()函数定义一个数据加载器。值得注意的一点是,数据中包括训练数据集和测试数据集两种!代码如下:
导入训练数据集:(其中参数train的定义值得注意,True代表导入训练集,False代表导入测试集)
#使用fashionMNSIT数据集 准备训练数据集
train_data = FashionMNIST(
root="./data/FashionMNIST",#路径
train = True,#只使用训练数据集 True说明导入训练集 False说明导入测试集
transform=transforms.ToTensor(),
download = True,
)
定义训练数据加载器,并输出batch数量(即为dataloader长度):
#定义一个数据加载器
train_loader = Data.DataLoader(
dataset=train_data,
batch_size=64,
shuffle=True,
num_workers=2,
)
#计算train_loader有多少batch
print("train_loader的batch数量=",len(train_loader))
结果为:
train_loader的batch数量= 938
导入测试数据集:
#使用fashionMNSIT数据集 准备测试数据集
test_data = FashionMNIST(
root="./data/FashionMNIST/",
train=False,
download=True,
)
将测试数据集中的像素值除以255.0以使像素值转化到0~1之间,再使用函数torch.unsqueeze()为数据添加一个维度即可得到最终的测试数据集。并且我们在测试数据集test_data中使用data()方法获取图像数据,使用targets()方法获取图像标签。代码如下:
test_data_x = test_data.data.type(torch.FloatTensor)/255.0#使用.data获取测试集图像数据#将数据集中像素除以255,使像素值转化到0~1
test_data_x = torch.unsqueeze(test_data_x,dim=1)#为数据添加一个通道
test_data_y = test_data.targets#使用.targets测试集标签
print("test_data_x.shape:",test_data_x.shape)
print("test_data_y.shape:",test_data_y.shape)
结果为:
test_data_x.shape: torch.Size([10000, 1, 28, 28])
test_data_y.shape: torch.Size([10000])
2.从文件夹中导入图片数据并进行预处理:
在torchvision的datasets模块中包含有ImageFolder函数,可以读取文件路径中的数据集。下面我们使用具体代码来演示使用过程,代码如下:
首先,为了读取如下路径中的图片:
在读取图片之前,我们首先需要设置训练数据集的变换操作,这里我们通过transforms.Compose()函数将多个图片变换操作组合在一起,代码如下:
#为了读取上面的文件夹中的图像 首先对训练数据集的变换操作进行设置
##对数据集的预处理
train_data_transforms = transforms.Compose([
#Compose:将多个transformer组合起来使用
transforms.RandomResizedCrop(224),#随机长宽比裁剪为224*224
transforms.RandomHorizontalFlip(),#依概率0.5随机翻转
transforms.ToTensor(),#转化为张量并归一化至(0-1)
#图像标准化处理
transforms.Normalize([0.485,0.456,0.406],
[0.229,0.224,0.225])#转换为标准正态分布
])
接下来,我们使用ImageFolder()函数读取图像,并定义一个数据加载器,代码如下:
#读取图像
train_data_dir = "data/chap2/imagedata/"
train_data = ImageFolder(train_data_dir,transform=train_data_transforms)
train_data_loader = Data.DataLoader(
dataset=train_data,
batch_size=4,
shuffle=True,
num_workers=1,
)
print("数据集的label:",train_data.targets)
#获得一个batch的数据
for step,(b_x,b_y) in enumerate(train_data_loader):
if step > 0:
break
print("b_x.shape",b_x.shape)
print("b_y.shape",b_y.shape)
print("图像的取值范围:",b_x.min(),"~",b_x.max())
其中,ImageFolder()函数中的transform参数 指定读取图像时对每张图像所做的变换。
结果如下,我们可以发现一共读取了3张图像,每张图像大小为224*224。
数据集的label: [0, 1, 2]
b_x.shape torch.Size([3, 3, 224, 224])
b_y.shape torch.Size([3])
图像的取值范围: tensor(-2.0152) ~ tensor(2.6400)