当前位置:   article > 正文

使用 DataLoader 和数据集训练 PyTorch 模型_一个dataloader里面应该是啥样的

一个dataloader里面应该是啥样的

面向读者:软件工程师、架构师、IT人士、设计人员等

所属专栏:人工智能工具实践

目录

概述

什么是DataLoader?

DataLoader在训练循环中使用

使用Dataset类创建数据迭代器

概括


当您构建和训练 PyTorch 深度学习模型时,您可以通过多种不同的方式提供训练数据。最终,PyTorch 模型的工作原理就像一个函数,它接受 PyTorch 张量并返回另一个张量。在如何获取输入张量方面您有很大的自由度。也许最简单的方法是准备整个数据集的大张量,并在每个训练步骤中从中提取一小批。但您会发现,使用DataLoader可以在处理数据时节省几行代码。

在这篇文章中,您将了解如何在 PyTorch 中使用数据和数据加载器。完成这篇文章后,您将了解到:

  • 如何创建和使用 DataLoader 来训练 PyTorch 模型
  • 如何使用 Data 类动态生成数据

概述

这篇文章分为三个部分;他们是:

  • 什么是DataLoader
  • DataLoader在训练循环中使用

什么是DataLoader

要训​​练深度学习模型,您需要数据。通常数据以数据集的形式提供。在数据集中,有大量的数据样本或实例。您可以要求模型一次采集一个样本,但通常您会让模型处理一批多个样本。您可以通过使用张量上的切片语法从数据集中提取切片来创建批次。为了获得更好的训练质量,您可能还需要在每个时期对整个数据集进行混洗,以便在整个训练循环中没有两个批次是相同的。有时,您可能会引入数据增强来手动向数据引入更多方差。这对于与图像相关的任务来说很常见,您可以随机倾斜或缩放图像一点,以从一些图像生成大量数据样本。

您可以想象需要编写大量代码来完成所有这些操作。但使用DataLoader.

DataLoader以下是如何创建批次并从中获取批次的示例。在此示例中,使用声呐数据集,最终将其转换为 PyTorch 张量并传递给:

  1. import pandas as pd
  2. import torch
  3. from torch.utils.data import Dataset, DataLoader
  4. from sklearn.preprocessing import LabelEncoder
  5.  
  6. # Read data, convert to NumPy arrays
  7. data = pd.read_csv("sonar.csv", header=None)
  8. X = data.iloc[:, 0:60].values
  9. y = data.iloc[:, 60].values
  10.  
  11. # encode class values as integers
  12. encoder = LabelEncoder()
  13. encoder.fit(y)
  14. y = encoder.transform(y)
  15.  
  16. # convert into PyTorch tensors
  17. X = torch.tensor(X, dtype=torch.float32)
  18. y = torch.tensor(y, dtype=torch.float32).reshape(-1, 1)
  19.  
  20. # create DataLoader, then take one batch
  21. loader = DataLoader(list(zip(X,y)), shuffle=True, batch_size=16)
  22. for X_batch, y_batch in loader:
  23.     print(X_batch, y_batch)
  24.     break

从上面的输出可以看出X_batchy_batch是 PyTorch 张量。是类loader的一个实例DataLoader,可以像迭代一样工作。每次读取时,您都会从原始数据集中获得一批特征和目标。

创建DataLoader实例时,您需要提供样本对列表。每个样本对是特征和对应目标的一个数据样本。需要一个列表,因为DataLoader期望使用len()来查找数据集的总大小并使用数组索引来检索特定样本。批次大小是一个参数,DataLoader因此它知道如何从整个数据集创建批次。您应该几乎总是使用shuffle=Trueso 每次加载数据时,样本都会被打乱。它对于训练很有用,因为在每个时期,您将读取每个批次一次。当您从一个时期进入另一个时期时,众所周知DataLoader您耗尽了所有批次,它将重新洗牌,以便您获得新的样本组合。

DataLoader在训练循环中使用

DataLoader以下是在训练循环中使用的示例:

  1. import torch
  2. import torch.nn as nn
  3. import torch.optim as optim
  4. from sklearn.model_selection import train_test_split
  5.  
  6. # train-test split for evaluation of the model
  7. X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, shuffle=True)
  8.  
  9. # set up DataLoader for training set
  10. loader = DataLoader(list(zip(X_train, y_train)), shuffle=True, batch_size=16)
  11.  
  12. # create model
  13. model = nn.Sequential(
  14.     nn.Linear(60, 60),
  15.     nn.ReLU(),
  16.     nn.Linear(60, 30),
  17.     nn.ReLU(),
  18.     nn.Linear(30, 1),
  19.     nn.Sigmoid()
  20. )
  21.  
  22. # Train the model
  23. n_epochs = 200
  24. loss_fn = nn.BCELoss()
  25. optimizer = optim.SGD(model.parameters(), lr=0.1)
  26. model.train()
  27. for epoch in range(n_epochs):
  28.     for X_batch, y_batch in loader:
  29.         y_pred = model(X_batch)
  30.         loss = loss_fn(y_pred, y_batch)
  31.         optimizer.zero_grad()
  32.         loss.backward()
  33.         optimizer.step()
  34.  
  35. # evaluate accuracy after training
  36. model.eval()
  37. y_pred = model(X_test)
  38. acc = (y_pred.round() == y_test).float().mean()
  39. acc = float(acc)
  40. print("Model accuracy: %.2f%%" % (acc*100))

您可以看到,一旦创建了DataLoader实例,训练循环就会变得更加容易。上面只用a打包了训练集,DataLoader因为需要批量循环。您还可DataLoader以为测试集创建 并将其用于模型评估,但由于准确性是在整个测试集而不是批量中计算的,因此带来的好处并不DataLoader显着。

将所有内容放在一起,下面是完整的代码。

  1. import pandas as pd
  2. import torch
  3. import torch.nn as nn
  4. import torch.optim as optim
  5. from torch.utils.data import DataLoader
  6. from sklearn.preprocessing import LabelEncoder
  7. from sklearn.model_selection import train_test_split
  8.  
  9. # Read data, convert to NumPy arrays
  10. data = pd.read_csv("sonar.csv", header=None)
  11. X = data.iloc[:, 0:60].values
  12. y = data.iloc[:, 60].values
  13.  
  14. # encode class values as integers
  15. encoder = LabelEncoder()
  16. encoder.fit(y)
  17. y = encoder.transform(y)
  18.  
  19. # convert into PyTorch tensors
  20. X = torch.tensor(X, dtype=torch.float32)
  21. y = torch.tensor(y, dtype=torch.float32).reshape(-1, 1)
  22.  
  23. # train-test split for evaluation of the model
  24. X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, shuffle=True)
  25.  
  26. # set up DataLoader for training set
  27. loader = DataLoader(list(zip(X_train, y_train)), shuffle=True, batch_size=16)
  28.  
  29. # create model
  30. model = nn.Sequential(
  31.     nn.Linear(60, 60),
  32.     nn.ReLU(),
  33.     nn.Linear(60, 30),
  34.     nn.ReLU(),
  35.     nn.Linear(30, 1),
  36.     nn.Sigmoid()
  37. )
  38.  
  39. # Train the model
  40. n_epochs = 200
  41. loss_fn = nn.BCELoss()
  42. optimizer = optim.SGD(model.parameters(), lr=0.1)
  43. model.train()
  44. for epoch in range(n_epochs):
  45.     for X_batch, y_batch in loader:
  46.         y_pred = model(X_batch)
  47.         loss = loss_fn(y_pred, y_batch)
  48.         optimizer.zero_grad()
  49.         loss.backward()
  50.         optimizer.step()
  51.  
  52. # evaluate accuracy after training
  53. model.eval()
  54. y_pred = model(X_test)
  55. acc = (y_pred.round() == y_test).float().mean()
  56. acc = float(acc)
  57. print("Model accuracy: %.2f%%" % (acc*100))

使用Dataset类创建数据迭代器

在PyTorch中,有一个Dataset类可以与DataLoader类紧密耦合。回想一下,DataLoader期望它的第一个参数可以与数组索引一起使用len()。该类Dataset是此类的基类。您可能想要使用Dataset类的原因是在获取数据样本之前需要进行一些特殊处理。例如,数据应该从数据库或磁盘读取,并且您只想在内存中保留一些样本,而不是预取所有内容。另一个例子是执行数据的实时预处理,例如图像任务中常见的随机增强。

要使用Dataset类,您只需从其子类化并实现两个成员函数即可。下面是一个例子:

  1. from torch.utils.data import Dataset
  2.  
  3. class SonarDataset(Dataset):
  4.     def __init__(self, X, y):
  5.         # convert into PyTorch tensors and remember them
  6.         self.X = torch.tensor(X, dtype=torch.float32)
  7.         self.y = torch.tensor(y, dtype=torch.float32)
  8.  
  9.     def __len__(self):
  10.         # this should return the size of the dataset
  11.         return len(self.X)
  12.  
  13.     def __getitem__(self, idx):
  14.         # this should return one sample from the dataset
  15.         features = self.X[idx]
  16.         target = self.y[idx]
  17.         return features, target
这不是最强大的使用方法 Dataset,但足够简单来演示它是如何工作的。有了这个,您可以创建一个 DataLoader并将其用于模型训练。根据前面的示例进行修改,您将得到以下内容:
  1. ...
  2.  
  3. # set up DataLoader for training set
  4. dataset = SonarDataset(X_train, y_train)
  5. loader = DataLoader(dataset, shuffle=True, batch_size=16)
  6.  
  7. # create model
  8. model = nn.Sequential(
  9.     nn.Linear(60, 60),
  10.     nn.ReLU(),
  11.     nn.Linear(60, 30),
  12.     nn.ReLU(),
  13.     nn.Linear(30, 1),
  14.     nn.Sigmoid()
  15. )
  16.  
  17. # Train the model
  18. n_epochs = 200
  19. loss_fn = nn.BCELoss()
  20. optimizer = optim.SGD(model.parameters(), lr=0.1)
  21. model.train()
  22. for epoch in range(n_epochs):
  23.     for X_batch, y_batch in loader:
  24.         y_pred = model(X_batch)
  25.         loss = loss_fn(y_pred, y_batch)
  26.         optimizer.zero_grad()
  27.         loss.backward()
  28.         optimizer.step()
  29.  
  30. # evaluate accuracy after training
  31. model.eval()
  32. y_pred = model(torch.tensor(X_test, dtype=torch.float32))
  33. y_test = torch.tensor(y_test, dtype=torch.float32)
  34. acc = (y_pred.round() == y_test).float().mean()
  35. acc = float(acc)
  36. print("Model accuracy: %.2f%%" % (acc*100))

您设置为实现了和功能 dataset的实例。这用于代替前面示例中的列表来设置实例。之后,训练循环中的一切都是一样的。请注意,您仍然直接使用 PyTorch 张量作为示例中的测试集。 SonarDataset __len__() __getitem__()DataLoader

在该__getitem__()函数中,您采用一个类似于数组索引的整数并返回一对,即特征和目标。您可以在此函数中实现任何内容:运行一些代码来生成合成数据样本、从互联网上动态读取数据或向数据添加随机变化。您还会发现它在您无法将整个数据集保留在内存中的情况下很有用,因此您可以仅加载您需要的数据样本。

事实上,既然您创建了 PyTorch 数据集,您就不需要使用 scikit-learn 将数据拆分为训练集和测试集。在子模块中,您有一个与类一起用于相同目的的torch.utils.data函数。完整的示例如下:random_split()Dataset

  1. import pandas as pd
  2. import torch
  3. import torch.nn as nn
  4. import torch.optim as optim
  5. from torch.utils.data import Dataset, DataLoader, random_split, default_collate
  6. from sklearn.preprocessing import LabelEncoder
  7.  
  8. # Read data, convert to NumPy arrays
  9. data = pd.read_csv("sonar.csv", header=None)
  10. X = data.iloc[:, 0:60].values
  11. y = data.iloc[:, 60].values
  12.  
  13. # encode class values as integers
  14. encoder = LabelEncoder()
  15. encoder.fit(y)
  16. y = encoder.transform(y).reshape(-1, 1)
  17.  
  18. class SonarDataset(Dataset):
  19.     def __init__(self, X, y):
  20.         # convert into PyTorch tensors and remember them
  21.         self.X = torch.tensor(X, dtype=torch.float32)
  22.         self.y = torch.tensor(y, dtype=torch.float32)
  23.  
  24.     def __len__(self):
  25.         # this should return the size of the dataset
  26.         return len(self.X)
  27.  
  28.     def __getitem__(self, idx):
  29.         # this should return one sample from the dataset
  30.         features = self.X[idx]
  31.         target = self.y[idx]
  32.         return features, target
  33.  
  34. # set up DataLoader for data set
  35. dataset = SonarDataset(X, y)
  36. trainset, testset = random_split(dataset, [0.7, 0.3])
  37. loader = DataLoader(trainset, shuffle=True, batch_size=16)
  38.  
  39. # create model
  40. model = nn.Sequential(
  41.     nn.Linear(60, 60),
  42.     nn.ReLU(),
  43.     nn.Linear(60, 30),
  44.     nn.ReLU(),
  45.     nn.Linear(30, 1),
  46.     nn.Sigmoid()
  47. )
  48.  
  49. # Train the model
  50. n_epochs = 200
  51. loss_fn = nn.BCELoss()
  52. optimizer = optim.SGD(model.parameters(), lr=0.1)
  53. model.train()
  54. for epoch in range(n_epochs):
  55.     for X_batch, y_batch in loader:
  56.         y_pred = model(X_batch)
  57.         loss = loss_fn(y_pred, y_batch)
  58.         optimizer.zero_grad()
  59.         loss.backward()
  60.         optimizer.step()
  61.  
  62. # create one test tensor from the testset
  63. X_test, y_test = default_collate(testset)
  64. model.eval()
  65. y_pred = model(X_test)
  66. acc = (y_pred.round() == y_test).float().mean()
  67. acc = float(acc)
  68. print("Model accuracy: %.2f%%" % (acc*100))
它与您之前的示例非常相似。请注意,PyTorch 模型仍然需要张量作为输入,而不是 Dataset. 因此,在上面,您需要使用该 default_collate()函数将数据集中的样本收集到张量中。

概括

在这篇文章中,您学习了如何使用DataLoader创建打乱的数据批次以及如何使用Dataset提供数据样本。具体来说,您学到了:

  • DataLoader作为向训练循环提供批量数据的便捷方式
  • 如何使用Dataset生成数据样本
  • 如何动态组合DatasetDataLoader生成批量数据以进行模型训练
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/482089
推荐阅读
相关标签
  

闽ICP备14008679号