当前位置:   article > 正文

(课程笔记)深度学习入门 - 8 - DataLoader

dataloader

一、DataLoader背景知识与概念

        定义:DataLoader是 PyTorch 提供的一个数据加载器,用于对数据进行批量加载和处理。它在训练神经网络时起到了重要的作用。它存在于 torch.utils.data 包下,需要的时候应该在该包下导入DataLoader。

        问题1:为什么需要DataLoader?

        神经网络的训练过程通常需要大量的数据,而将所有数据一次性加载到内存中是不可行的。这时候就需要使用 DataLoader 将数据分成小批次进行加载。DataLoader 可以自动完成数据的批量加载、随机洗牌(shuffle)、并发预取等操作,从而提高模型训练的效率。

        问题2:DataLoader有什么特点?

        (1)批处理: DataLoader 可以将数据分成小批次进行加载,从而使得每次迭代都能处理多个数据样本。

        (2)随机洗牌(shuffle): DataLoader 具有随机洗牌功能,可以在每个迭代之前将数据顺序打乱,从而减少模型对输入数据的依赖性。

        (3)并发预取(prefetching): DataLoader 可以使用多线程或多进程来提前预取数据,充分利用 CPU 的性能,加速数据加载过程。

        (4)方便的数据转换: DataLoader 可以通过自定义的数据转换函数对原始数据进行预处理,如裁剪、缩放、标准化等。

二、DataLoader的参数设计

1、DataLoader 的常用参数

dataset: 指定数据集,通常是 torch.utils.data.Dataset 类的实例。

batch_size: 每个批次的样本数量。

shuffle: 是否对数据进行洗牌操作。

num_workers: 加载数据时的并发线程或进程数。

drop_last: 当数据样本数量不能被批次大小整除时,是否丢弃最后一个不完整的批次。

collate_fn: 自定义的数据处理函数,用于将多个样本汇集到一个批次中。‘’

2、DataLoader的参数设计建议

        在调整 DataLoader 的参数时,需要根据具体问题和数据集的特点进行考虑。以下是一些常见的调整方法:

(1)batch_size根据可用内存和模型的需求,增加或减少批次大小。较大的批次大小可以提高训练速度,但也可能会增加内存占用。

(2)shuffle是否进行随机洗牌:对于训练数据,通常会设置为 True来减少模型对输入数据顺序的依赖性。对于验证和测试数据,通常会设置为False。

(3)num_workers根据计算机硬件的配置和数据加载的速度来设置,并发加载数据以加快训练速度。但是,过多的并行加载也可能会导致性能下降,因此需要进行适当的调整。

(4)drop_last默认情况下, DataLoader 不会丢弃最后一个不完整的批次。但是,在内存有限的情况下,如果内存无法容纳一个完整的批次,可以将 drop_last 设置为 True,丢弃最后一个不完整的批次。

三、用DataLoader实现神经网络训练

0、导包

  1. import numpy as np
  2. import torch
  3. from torch.utils.data import Dataset, DataLoader

1、准备数据集与DataLoader

  1. class DiabetesDataset(Dataset):
  2. # DiabetesDataset类继承自torch.utils.data.Dataset
  3. # 重写了__init__、__getitem__和__len__方法。
  4. # 1、__init__方法:它加载了名为"diabetes.csv.gz"的数据文件
  5. # 并将数据划分为输入特征(x_data)和目标标签(y_data)。
  6. # x_data是除最后一列之外的所有列,y_data是最后一列。
  7. # 同时,它还记录了数据集的长度。
  8. # 2、__getitem__方法:用于获取指定索引的样本,返回的是该索引
  9. # 处的输入特征和目标标签。
  10. # 3、__len__方法:返回数据集的长度。
  11. def __init__(self, filePath):
  12. xy_data_set = np.loadtxt(filePath, delimiter=',', dtype=np.float32)
  13. self.len = xy_data_set.shape[0]
  14. self.x_data = torch.from_numpy(xy_data_set[:, :-1])
  15. self.y_data = torch.from_numpy(xy_data_set[:, [-1]])
  16. def __getitem__(self, index):
  17. return self.x_data[index], self.y_data[index]
  18. def __len__(self):
  19. return self.len
  20. # 最后,在创建了DiabetesDataset对象后,使用DataLoader对数据集
  21. # 进行批处理,每批大小为32,打乱顺序,并开启2个工作进程。
  22. dataset = DiabetesDataset("diabetes.csv.gz")
  23. train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)

        要使用DataLoader去训练神经网络,首先要构建一个类,让这个类继承至Dataset,在这个类中重写3个方法,分别是:init,getitem,len。它们的作用分别是:

        (1)init:初始化代码,给定数据集的filePath,可以进行输入和输出的切割操作,并且记录了这个数据集有多少行,即:有多少个样本;

        (2)getitem:主要是返回指定index处的输入特征以及输出标签值

        (3)len:主要是返回数据集的样本数

        完成类的编写后,利用其构造器,传入数据集的文件路径,生成一个Dataset的实例化对象,此时开始生成DataLoader对象,利用DataLoader类的构造器,传入代表数据集的变量(dataset=?),传入批量处理数据的容量(batch_size=?),决定是否打乱数据集的数据内容(shuffle=?),设置并行线程数量(num_workers=?),这样我们就得到了一个DataLoader对象,并已经设置好了它的参数。

2、创建模型

  1. class Model(torch.nn.Module):
  2. def __init__(self):
  3. super(Model, self).__init__()
  4. self.linear1 = torch.nn.Linear(8, 6)
  5. self.linear2 = torch.nn.Linear(6, 4)
  6. self.linear3 = torch.nn.Linear(4, 1)
  7. self.sigmoid = torch.nn.Sigmoid()
  8. def forward(self, x):
  9. x = self.sigmoid(self.linear1(x))
  10. x = self.sigmoid(self.linear2(x))
  11. y_pred = self.sigmoid(self.linear3(x))
  12. return y_pred
  13. model = Model()

3、创建损失函数和优化器

  1. BCE_Loss = torch.nn.BCELoss(reduction="mean")
  2. SGD_optm = torch.optim.SGD(model.parameters(), lr=0.03)

4、开始训练

  1. if __name__ == '__main__':
  2. epochs = 100
  3. # 设定训练的总轮数(epoch),每个epoch表示将整个数据集完整地通过模型一次。
  4. for epoch in range(epochs):
  5. # 使用enumerate函数遍历train_loader中的每个批次数据。
  6. # enumerate(train_loader, 0)的返回结果是一个可迭代对象iteration
  7. # 每次迭代会返回一个元组(index, dataTuple),其中包含了索引和对应的数据元组。
  8. # i表示当前批次的索引,data包含当前批次的输入特征和目标标签。(索引从0开始)
  9. for i, data in enumerate(train_loader, 0):
  10. x_data, y_label = data
  11. y_predict = model(x_data)
  12. loss = BCE_Loss(y_predict, y_label)
  13. print(f"Epoch = {epoch+1}, Part = {i}, Loss = {loss.item()}")
  14. SGD_optm.zero_grad()
  15. loss.backward()
  16. SGD_optm.step()

        这里需要注意的是:我们准备训练100轮,一轮训练32个试验数据,共计会训练3200个样本用于训练模型,循环开始时,我们需要用enumerate()函数把第一批得到的32个样本进行拆解,该函数需要传入一个DataLoader,再传入一个初始索引值,即:enumerate(train_loader , 0)。

        传入参数后,该函数会返回2个结果,第一个是index值(本节初始index为0),第二个是data元组,里面包含了这一批量样本的输入特征与输出标签值,所以要用 x_data 和 y_label 来接收这个元组中的数据。

        接收到数据后,就可以开始训练模型,以及计算损失函数了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/455061
推荐阅读
相关标签
  

闽ICP备14008679号