【PyTorch基础教程8】dataset和dataloader

简介: 使用torch.nn创建神经网络,nn包会使用autograd包定义模型和求梯度。一个nn.Module对象包括了许多网络层,并且用forward(input)方法来计算损失值,返回output。

零、训练DNN的过程

image.png

使用torch.nn创建神经网络,nn包会使用autograd包定义模型和求梯度。一个nn.Module对象包括了许多网络层,并且用forward(input)方法来计算损失值,返回output。

训练一个神经网络通畅需要以下步骤:

定义一个神经网络,通常有一些可以训练的参数

迭代一个数据集(Dataset)

处理网络的输入

计算损失(会调用Module对象的forward()方法)

计算损失函数对参数的梯度

更新参数,通常使用如下的梯度下降方法来更新:weight=weight-learning_rate × gradien。

一、读入数据

1.1 参数解读

PyTorch数据读入是通过Dataset+Dataloader的方式完成的。

Dataset定义好数据的格式和数据变换形式,用来构造数据集。从而数据集支持【索引】,通过下标将样本取出

Dataloader用iterative的方式不断读入批次数据。Dataloader用来拿出一个mini-batch。

我们可以定义自己的Dataset类来实现灵活的数据读取,定义的类需要继承PyTorch自身的Dataset类。主要包含三个函数:

__init__: 用于向类中传入外部参数,同时定义样本集

__getitem__: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据

__len__: 用于返回数据集的样本数

1.2 代码栗子

下面以cifar10数据集为例给出构建Dataset类的方式:

train_data = datasets.ImageFolder(train_path, 
                  transform=data_transform)
val_data = datasets.ImageFolder(val_path, 
                transform=data_transform)

这里使用了PyTorch自带的ImageFolder类的用于读取按一定结构存储的图片数据(path对应图片存放的目录,目录下包含若干子目录,每个子目录对应一个类的图片)。

其中data_transform可以对图像进行一定的变换,如翻转、裁剪等操作,可自己定义。

另一个例子:其中图片存放在一个文件夹,另外有一个csv文件给出了图片名称对应的标签。这种情况下需要自己来定义Dataset类:

class MyDataset(Dataset):
    def __init__(self, data_dir, info_csv, image_list, transform=None):
        """
        Args:
            data_dir: path to image directory.
            info_csv: path to the csv file containing image indexes
                with corresponding labels.
            image_list: path to the txt file contains image names to training/validation set
            transform: optional transform to be applied on a sample.
        """
        label_info = pd.read_csv(info_csv)
        image_file = open(image_list).readlines()
        self.data_dir = data_dir
        self.image_file = image_file
        self.label_info = label_info
        self.transform = transform
    def __getitem__(self, index):
        """
        Args:
            index: the index of item
        Returns:
            image and its labels
        """
        image_name = self.image_file[index].strip('\n')
        raw_label = self.label_info.loc[self.label_info['Image_index'] == image_name]
        label = raw_label.iloc[:,0]
        image_name = os.path.join(self.data_dir, image_name)
        image = Image.open(image_name).convert('RGB')
        if self.transform is not None:
            image = self.transform(image)
        return image, label
    def __len__(self):
        return len(self.image_file)

构建好Datadet后,就可以使用DataLoader来按批次读入数据了,实现代码如下:

train_loader = torch.utils.data.DataLoader( train_data, 
                      batch_size=batch_size, 
                      num_workers=4, 
                      shuffle=True, 
                      drop_last=True)
val_loader = torch.utils.data.DataLoader(val_data, 
                     batch_size=batch_size, 
                     num_workers=4, 
                     shuffle=False)

其中:

batch_size:样本是按“批”读入的,batch_size就是每次读入的样本数

num_workers:有多少个进程用于读取数据(在构成mini-batch的过程中)

shuffle:是否将读入的数据打乱

drop_last:对于样本最后一部分没有达到批次数的样本,不再参与训练

看加载的数据。PyTorch中的DataLoader的读取可以使用next和iter来完成。

import matplotlib.pyplot as plt
images, labels = next(iter(val_loader))
print(images.shape)
plt.imshow(images[0].transpose(1,2,0))
plt.show()

二、Epoch,Batch-size,Iterations

外层for为训练周期,内层for迭代mini-batch。

(1)epoch:将所有的训练样本都进行了一次前向传递和反向传播,是一个epoch。

(2)Batch-size:每次训练所用的样本数量

(3)Iteration:内层for执行的次数。

ex:共有10000个样本,batch-size=1000,即每次拿1000个样本进行训练,则Iteration=10次。

image.png

加载数据集的两种方法:

(1)all data:适合数据集比较小的

(2)大数据类似几十G的图像数据或语音等无结构数据:加载部分。

linux和win系统的多进程库是不同的:在win中是用spawn替代linux的fork(创建一个新进程)。所以要将把loader进行迭代的代码进行封装起来(如if语句或者函数里面,即不能直接写在外面), 也可以直接外面加上if __name__ == '__main__':。

三、糖尿病数据集处理

(1)因为该数据集较小,所以将所有的数据和标签都加载到self.x_data和self.y_data(在内存中)中了。 在__getitem__函数内当传参(x, y)时,别看形式参数好像只有index,但其实返回的是元组(x, y)(回顾之前的*args)。

(2)为了获得当前是第几次迭代,可以用enumerate,这样就可以获得下标i即当前的迭代次数。在训练的内循环中,每次拿出的data是一个元组(x, y)。而dataloader会自动将多个data组合成Tensor矩阵(所以不需要我们自己组成tensor)。

(3)训练过程和之前类似,只是为了使用mini-batch方式训练,嵌套了内层的for循环。

在测试中的dataloader一般设置shuffle = False即不用shuffle(洗不洗影响不大)。

# -*- coding: utf-8 -*-
"""
Created on Mon Oct 18 14:06:02 2021
@author: 86493
"""
import numpy as np
import torch
import torch.nn as nn
# Dataset是抽象类(不能实例化,只能被子类继承)
from torch.utils.data import Dataset 
# dataloader做shuffle、batchsize等,可实例
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
losslst = []
# 构建自己的数据集类
class DiabetesDataset(Dataset):
    def __init__(self, filepath):
        # 一般类型用np.float32位,而不用double
        xy = np.loadtxt(filepath, 
                        delimiter = ' ',
                        dtype = np.float32)
        self.len = xy.shape[0]
        # 最后一列不要,即要前9列,不要最后的一列
        self.x_data = torch.from_numpy(xy[:, :-1])
        # [-1]则拿出来的是一个矩阵,去了中括号则拿出向量
        self.y_data = torch.from_numpy(xy[:, [-1]])
    # magic function
    # 后面可以用dataset[index]
    def __getitem__(self, index): 
        return self.x_data[index], self.y_data[index]
    # 返回数据集的length,即数据条数
    def __len__(self): 
        return self.len 
dataset = DiabetesDataset('diabetes.csv')
"""
train_loader = DataLoader(dataset = dataset,
                          batch_size = 4,
                          shuffle = True,
                          num_workers = 1)
"""
train_loader = DataLoader(dataset = dataset,
                          batch_size = 32,
                          shuffle = True)
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = nn.Linear(9, 6)
        self.linear2 = nn.Linear(6, 4)
        self.linear3 = nn.Linear(4, 1)
        self.sigmoid = nn.Sigmoid()
    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x
model = Model()
# 使用交叉熵
# criterion = nn.BCELoss(size_average = True)
criterion = nn.BCELoss(reduction = 'mean')
optimizer = torch.optim.SGD(model.parameters(),
                            lr = 0.01)
# batch处理
if __name__ == '__main__':
    for epoch in range(50):
        # 内层循环执行一个mini-batch
        for i, data in enumerate(train_loader, 0):
        # 也可以写成for i, (input, labels) in enumerate(train_loader, 0):
            # 1.准备数据
            inputs, labels = data 
            # 2.向前传递
            y_predict = model(inputs)
            loss = criterion(y_predict, labels)
            losslst.append(loss.item())
            print(epoch, i, loss.item())
            # 3.反向传播
            optimizer.zero_grad()
            loss.backward()
            # 4.更新参数
            optimizer.step()
# 画图
plt.plot(range(700), losslst)
plt.xlabel("epoch")
plt.ylabel("Loss")
plt.show()

image.png

四、作业

(1)使用torchvision.datasets,其中也有很多数据集,如MNIST、Fashion-MNIST、EMNIST、COCO、LSUN、ImageFolder、DatasetFolder、Imagenet-12、CIFAR、STL10、PhotoTour等数据集。

image.png

(2)Build DataLoader for:

• Titanic dataset: https://www.kaggle.com/c/titanic/data

• Build a classifier using the DataLoader

Reference

相关文章
|
30天前
|
机器学习/深度学习 PyTorch 算法框架/工具
【单点知识】基于实例详解PyTorch中的DataLoader类
【单点知识】基于实例详解PyTorch中的DataLoader类
120 2
|
4月前
|
数据采集 PyTorch 算法框架/工具
PyTorch基础之数据模块Dataset、DataLoader用法详解(附源码)
PyTorch基础之数据模块Dataset、DataLoader用法详解(附源码)
392 0
|
8月前
|
PyTorch 算法框架/工具 索引
Pytorch学习笔记(2):数据读取机制(DataLoader与Dataset)
Pytorch学习笔记(2):数据读取机制(DataLoader与Dataset)
397 0
Pytorch学习笔记(2):数据读取机制(DataLoader与Dataset)
|
10月前
|
机器学习/深度学习 PyTorch 算法框架/工具
Pytorch使用专题 | 2 :Pytorch中数据读取-Dataset、Dataloader 、TensorDataset 和 Sampler 的使用
介绍Pytorch中数据读取-Dataset、Dataloader 、TensorDataset 和 Sampler 的使用
|
9月前
|
PyTorch 算法框架/工具 索引
Pytorch: 数据读取机制Dataloader与Dataset
Pytorch: 数据读取机制Dataloader与Dataset
179 0
|
10月前
|
机器学习/深度学习 PyTorch 算法框架/工具
Pytorch中如何使用DataLoader对数据集进行批训练
Pytorch中如何使用DataLoader对数据集进行批训练
95 0
|
10月前
|
PyTorch 算法框架/工具
【PyTorch】自定义数据集处理/dataset/DataLoader等
【PyTorch】自定义数据集处理/dataset/DataLoader等
119 0
|
10月前
|
机器学习/深度学习 数据采集 PyTorch
pytorch笔记:Dataset 和 DataLoader
pytorch笔记:Dataset 和 DataLoader
218 0
|
2月前
|
机器学习/深度学习 编解码 PyTorch
Pytorch实现手写数字识别 | MNIST数据集(CNN卷积神经网络)
Pytorch实现手写数字识别 | MNIST数据集(CNN卷积神经网络)
|
30天前
|
机器学习/深度学习 算法 PyTorch
【PyTorch实战演练】深入剖析MTCNN(多任务级联卷积神经网络)并使用30行代码实现人脸识别
【PyTorch实战演练】深入剖析MTCNN(多任务级联卷积神经网络)并使用30行代码实现人脸识别
54 2