赞
踩
定义:DataLoader是 PyTorch 提供的一个数据加载器,用于对数据进行批量加载和处理。它在训练神经网络时起到了重要的作用。它存在于 torch.utils.data 包下,需要的时候应该在该包下导入DataLoader。
问题1:为什么需要DataLoader?
神经网络的训练过程通常需要大量的数据,而将所有数据一次性加载到内存中是不可行的。这时候就需要使用 DataLoader 将数据分成小批次进行加载。DataLoader 可以自动完成数据的批量加载、随机洗牌(shuffle)、并发预取等操作,从而提高模型训练的效率。
问题2:DataLoader有什么特点?
(1)批处理: DataLoader 可以将数据分成小批次进行加载,从而使得每次迭代都能处理多个数据样本。
(2)随机洗牌(shuffle): DataLoader 具有随机洗牌功能,可以在每个迭代之前将数据顺序打乱,从而减少模型对输入数据的依赖性。
(3)并发预取(prefetching): DataLoader 可以使用多线程或多进程来提前预取数据,充分利用 CPU 的性能,加速数据加载过程。
(4)方便的数据转换: DataLoader 可以通过自定义的数据转换函数对原始数据进行预处理,如裁剪、缩放、标准化等。
dataset
: 指定数据集,通常是 torch.utils.data.Dataset
类的实例。
batch_size
: 每个批次的样本数量。
shuffle
: 是否对数据进行洗牌操作。
num_workers
: 加载数据时的并发线程或进程数。
drop_last
: 当数据样本数量不能被批次大小整除时,是否丢弃最后一个不完整的批次。
collate_fn
: 自定义的数据处理函数,用于将多个样本汇集到一个批次中。‘’
在调整 DataLoader 的参数时,需要根据具体问题和数据集的特点进行考虑。以下是一些常见的调整方法:
(1)batch_size
:根据可用内存和模型的需求,增加或减少批次大小。较大的批次大小可以提高训练速度,但也可能会增加内存占用。
(2)shuffle
: 是否进行随机洗牌:对于训练数据,通常会设置为 True来减少模型对输入数据顺序的依赖性。对于验证和测试数据,通常会设置为False。
(3)num_workers
:根据计算机硬件的配置和数据加载的速度来设置,并发加载数据以加快训练速度。但是,过多的并行加载也可能会导致性能下降,因此需要进行适当的调整。
(4)drop_last
:默认情况下, DataLoader 不会丢弃最后一个不完整的批次。但是,在内存有限的情况下,如果内存无法容纳一个完整的批次,可以将 drop_last
设置为 True,丢弃最后一个不完整的批次。
- import numpy as np
- import torch
- from torch.utils.data import Dataset, DataLoader
- class DiabetesDataset(Dataset):
-
- # DiabetesDataset类继承自torch.utils.data.Dataset
- # 重写了__init__、__getitem__和__len__方法。
-
- # 1、__init__方法:它加载了名为"diabetes.csv.gz"的数据文件
- # 并将数据划分为输入特征(x_data)和目标标签(y_data)。
- # x_data是除最后一列之外的所有列,y_data是最后一列。
- # 同时,它还记录了数据集的长度。
-
- # 2、__getitem__方法:用于获取指定索引的样本,返回的是该索引
- # 处的输入特征和目标标签。
-
- # 3、__len__方法:返回数据集的长度。
-
-
-
- def __init__(self, filePath):
- xy_data_set = np.loadtxt(filePath, delimiter=',', dtype=np.float32)
- self.len = xy_data_set.shape[0]
- self.x_data = torch.from_numpy(xy_data_set[:, :-1])
- self.y_data = torch.from_numpy(xy_data_set[:, [-1]])
-
-
- def __getitem__(self, index):
- return self.x_data[index], self.y_data[index]
-
-
- def __len__(self):
- return self.len
-
- # 最后,在创建了DiabetesDataset对象后,使用DataLoader对数据集
- # 进行批处理,每批大小为32,打乱顺序,并开启2个工作进程。
-
- dataset = DiabetesDataset("diabetes.csv.gz")
- 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对象,并已经设置好了它的参数。
- class Model(torch.nn.Module):
- def __init__(self):
- super(Model, self).__init__()
- self.linear1 = torch.nn.Linear(8, 6)
- self.linear2 = torch.nn.Linear(6, 4)
- self.linear3 = torch.nn.Linear(4, 1)
- self.sigmoid = torch.nn.Sigmoid()
-
- def forward(self, x):
- x = self.sigmoid(self.linear1(x))
- x = self.sigmoid(self.linear2(x))
- y_pred = self.sigmoid(self.linear3(x))
- return y_pred
-
- model = Model()
- BCE_Loss = torch.nn.BCELoss(reduction="mean")
- SGD_optm = torch.optim.SGD(model.parameters(), lr=0.03)
- if __name__ == '__main__':
- epochs = 100
-
- # 设定训练的总轮数(epoch),每个epoch表示将整个数据集完整地通过模型一次。
- for epoch in range(epochs):
-
- # 使用enumerate函数遍历train_loader中的每个批次数据。
- # enumerate(train_loader, 0)的返回结果是一个可迭代对象iteration
- # 每次迭代会返回一个元组(index, dataTuple),其中包含了索引和对应的数据元组。
- # i表示当前批次的索引,data包含当前批次的输入特征和目标标签。(索引从0开始)
-
- for i, data in enumerate(train_loader, 0):
-
- x_data, y_label = data
- y_predict = model(x_data)
- loss = BCE_Loss(y_predict, y_label)
-
- print(f"Epoch = {epoch+1}, Part = {i}, Loss = {loss.item()}")
-
- SGD_optm.zero_grad()
- loss.backward()
- SGD_optm.step()
这里需要注意的是:我们准备训练100轮,一轮训练32个试验数据,共计会训练3200个样本用于训练模型,循环开始时,我们需要用enumerate()函数把第一批得到的32个样本进行拆解,该函数需要传入一个DataLoader,再传入一个初始索引值,即:enumerate(train_loader , 0)。
传入参数后,该函数会返回2个结果,第一个是index值(本节初始index为0),第二个是data元组,里面包含了这一批量样本的输入特征与输出标签值,所以要用 x_data 和 y_label 来接收这个元组中的数据。
接收到数据后,就可以开始训练模型,以及计算损失函数了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。