赞
踩
✍面向读者:软件工程师、架构师、IT人士、设计人员等
✍所属专栏:人工智能工具实践
目录
当您构建和训练 PyTorch 深度学习模型时,您可以通过多种不同的方式提供训练数据。最终,PyTorch 模型的工作原理就像一个函数,它接受 PyTorch 张量并返回另一个张量。在如何获取输入张量方面您有很大的自由度。也许最简单的方法是准备整个数据集的大张量,并在每个训练步骤中从中提取一小批。但您会发现,使用DataLoader
可以在处理数据时节省几行代码。
在这篇文章中,您将了解如何在 PyTorch 中使用数据和数据加载器。完成这篇文章后,您将了解到:
这篇文章分为三个部分;他们是:
DataLoader
?DataLoader
在训练循环中使用DataLoader
?要训练深度学习模型,您需要数据。通常数据以数据集的形式提供。在数据集中,有大量的数据样本或实例。您可以要求模型一次采集一个样本,但通常您会让模型处理一批多个样本。您可以通过使用张量上的切片语法从数据集中提取切片来创建批次。为了获得更好的训练质量,您可能还需要在每个时期对整个数据集进行混洗,以便在整个训练循环中没有两个批次是相同的。有时,您可能会引入数据增强来手动向数据引入更多方差。这对于与图像相关的任务来说很常见,您可以随机倾斜或缩放图像一点,以从一些图像生成大量数据样本。
您可以想象需要编写大量代码来完成所有这些操作。但使用DataLoader
.
DataLoader
以下是如何创建批次并从中获取批次的示例。在此示例中,使用声呐数据集,最终将其转换为 PyTorch 张量并传递给:
- import pandas as pd
- import torch
- from torch.utils.data import Dataset, DataLoader
- from sklearn.preprocessing import LabelEncoder
-
- # Read data, convert to NumPy arrays
- data = pd.read_csv("sonar.csv", header=None)
- X = data.iloc[:, 0:60].values
- y = data.iloc[:, 60].values
-
- # encode class values as integers
- encoder = LabelEncoder()
- encoder.fit(y)
- y = encoder.transform(y)
-
- # convert into PyTorch tensors
- X = torch.tensor(X, dtype=torch.float32)
- y = torch.tensor(y, dtype=torch.float32).reshape(-1, 1)
-
- # create DataLoader, then take one batch
- loader = DataLoader(list(zip(X,y)), shuffle=True, batch_size=16)
- for X_batch, y_batch in loader:
- print(X_batch, y_batch)
- break
从上面的输出可以看出X_batch
和y_batch
是 PyTorch 张量。是类loader
的一个实例DataLoader
,可以像迭代一样工作。每次读取时,您都会从原始数据集中获得一批特征和目标。
创建DataLoader
实例时,您需要提供样本对列表。每个样本对是特征和对应目标的一个数据样本。需要一个列表,因为DataLoader
期望使用len()
来查找数据集的总大小并使用数组索引来检索特定样本。批次大小是一个参数,DataLoader
因此它知道如何从整个数据集创建批次。您应该几乎总是使用shuffle=True
so 每次加载数据时,样本都会被打乱。它对于训练很有用,因为在每个时期,您将读取每个批次一次。当您从一个时期进入另一个时期时,众所周知DataLoader
您耗尽了所有批次,它将重新洗牌,以便您获得新的样本组合。
DataLoader
在训练循环中使用DataLoader
以下是在训练循环中使用的示例:
- import torch
- import torch.nn as nn
- import torch.optim as optim
- from sklearn.model_selection import train_test_split
-
- # train-test split for evaluation of the model
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, shuffle=True)
-
- # set up DataLoader for training set
- loader = DataLoader(list(zip(X_train, y_train)), shuffle=True, batch_size=16)
-
- # create model
- model = nn.Sequential(
- nn.Linear(60, 60),
- nn.ReLU(),
- nn.Linear(60, 30),
- nn.ReLU(),
- nn.Linear(30, 1),
- nn.Sigmoid()
- )
-
- # Train the model
- n_epochs = 200
- loss_fn = nn.BCELoss()
- optimizer = optim.SGD(model.parameters(), lr=0.1)
- model.train()
- for epoch in range(n_epochs):
- for X_batch, y_batch in loader:
- y_pred = model(X_batch)
- loss = loss_fn(y_pred, y_batch)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
-
- # evaluate accuracy after training
- model.eval()
- y_pred = model(X_test)
- acc = (y_pred.round() == y_test).float().mean()
- acc = float(acc)
- print("Model accuracy: %.2f%%" % (acc*100))
您可以看到,一旦创建了DataLoader
实例,训练循环就会变得更加容易。上面只用a打包了训练集,DataLoader
因为需要批量循环。您还可DataLoader
以为测试集创建 并将其用于模型评估,但由于准确性是在整个测试集而不是批量中计算的,因此带来的好处并不DataLoader
显着。
将所有内容放在一起,下面是完整的代码。
- import pandas as pd
- import torch
- import torch.nn as nn
- import torch.optim as optim
- from torch.utils.data import DataLoader
- from sklearn.preprocessing import LabelEncoder
- from sklearn.model_selection import train_test_split
-
- # Read data, convert to NumPy arrays
- data = pd.read_csv("sonar.csv", header=None)
- X = data.iloc[:, 0:60].values
- y = data.iloc[:, 60].values
-
- # encode class values as integers
- encoder = LabelEncoder()
- encoder.fit(y)
- y = encoder.transform(y)
-
- # convert into PyTorch tensors
- X = torch.tensor(X, dtype=torch.float32)
- y = torch.tensor(y, dtype=torch.float32).reshape(-1, 1)
-
- # train-test split for evaluation of the model
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, shuffle=True)
-
- # set up DataLoader for training set
- loader = DataLoader(list(zip(X_train, y_train)), shuffle=True, batch_size=16)
-
- # create model
- model = nn.Sequential(
- nn.Linear(60, 60),
- nn.ReLU(),
- nn.Linear(60, 30),
- nn.ReLU(),
- nn.Linear(30, 1),
- nn.Sigmoid()
- )
-
- # Train the model
- n_epochs = 200
- loss_fn = nn.BCELoss()
- optimizer = optim.SGD(model.parameters(), lr=0.1)
- model.train()
- for epoch in range(n_epochs):
- for X_batch, y_batch in loader:
- y_pred = model(X_batch)
- loss = loss_fn(y_pred, y_batch)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
-
- # evaluate accuracy after training
- model.eval()
- y_pred = model(X_test)
- acc = (y_pred.round() == y_test).float().mean()
- acc = float(acc)
- print("Model accuracy: %.2f%%" % (acc*100))
Dataset
类创建数据迭代器在PyTorch中,有一个Dataset
类可以与DataLoader
类紧密耦合。回想一下,DataLoader
期望它的第一个参数可以与数组索引一起使用len()
。该类Dataset
是此类的基类。您可能想要使用Dataset
类的原因是在获取数据样本之前需要进行一些特殊处理。例如,数据应该从数据库或磁盘读取,并且您只想在内存中保留一些样本,而不是预取所有内容。另一个例子是执行数据的实时预处理,例如图像任务中常见的随机增强。
要使用Dataset
类,您只需从其子类化并实现两个成员函数即可。下面是一个例子:
- from torch.utils.data import Dataset
-
- class SonarDataset(Dataset):
- def __init__(self, X, y):
- # convert into PyTorch tensors and remember them
- self.X = torch.tensor(X, dtype=torch.float32)
- self.y = torch.tensor(y, dtype=torch.float32)
-
- def __len__(self):
- # this should return the size of the dataset
- return len(self.X)
-
- def __getitem__(self, idx):
- # this should return one sample from the dataset
- features = self.X[idx]
- target = self.y[idx]
- return features, target
Dataset
,但足够简单来演示它是如何工作的。有了这个,您可以创建一个
DataLoader
并将其用于模型训练。根据前面的示例进行修改,您将得到以下内容:
- ...
-
- # set up DataLoader for training set
- dataset = SonarDataset(X_train, y_train)
- loader = DataLoader(dataset, shuffle=True, batch_size=16)
-
- # create model
- model = nn.Sequential(
- nn.Linear(60, 60),
- nn.ReLU(),
- nn.Linear(60, 30),
- nn.ReLU(),
- nn.Linear(30, 1),
- nn.Sigmoid()
- )
-
- # Train the model
- n_epochs = 200
- loss_fn = nn.BCELoss()
- optimizer = optim.SGD(model.parameters(), lr=0.1)
- model.train()
- for epoch in range(n_epochs):
- for X_batch, y_batch in loader:
- y_pred = model(X_batch)
- loss = loss_fn(y_pred, y_batch)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
-
- # evaluate accuracy after training
- model.eval()
- y_pred = model(torch.tensor(X_test, dtype=torch.float32))
- y_test = torch.tensor(y_test, dtype=torch.float32)
- acc = (y_pred.round() == y_test).float().mean()
- acc = float(acc)
- print("Model accuracy: %.2f%%" % (acc*100))
dataset
的实例。这用于代替前面示例中的列表来设置实例。之后,训练循环中的一切都是一样的。请注意,您仍然直接使用 PyTorch 张量作为示例中的测试集。
SonarDataset
__len__()
__getitem__()DataLoader
在该__getitem__()
函数中,您采用一个类似于数组索引的整数并返回一对,即特征和目标。您可以在此函数中实现任何内容:运行一些代码来生成合成数据样本、从互联网上动态读取数据或向数据添加随机变化。您还会发现它在您无法将整个数据集保留在内存中的情况下很有用,因此您可以仅加载您需要的数据样本。
事实上,既然您创建了 PyTorch 数据集,您就不需要使用 scikit-learn 将数据拆分为训练集和测试集。在子模块中,您有一个与类一起用于相同目的的torch.utils.data
函数。完整的示例如下:random_split()Dataset
- import pandas as pd
- import torch
- import torch.nn as nn
- import torch.optim as optim
- from torch.utils.data import Dataset, DataLoader, random_split, default_collate
- from sklearn.preprocessing import LabelEncoder
-
- # Read data, convert to NumPy arrays
- data = pd.read_csv("sonar.csv", header=None)
- X = data.iloc[:, 0:60].values
- y = data.iloc[:, 60].values
-
- # encode class values as integers
- encoder = LabelEncoder()
- encoder.fit(y)
- y = encoder.transform(y).reshape(-1, 1)
-
- class SonarDataset(Dataset):
- def __init__(self, X, y):
- # convert into PyTorch tensors and remember them
- self.X = torch.tensor(X, dtype=torch.float32)
- self.y = torch.tensor(y, dtype=torch.float32)
-
- def __len__(self):
- # this should return the size of the dataset
- return len(self.X)
-
- def __getitem__(self, idx):
- # this should return one sample from the dataset
- features = self.X[idx]
- target = self.y[idx]
- return features, target
-
- # set up DataLoader for data set
- dataset = SonarDataset(X, y)
- trainset, testset = random_split(dataset, [0.7, 0.3])
- loader = DataLoader(trainset, shuffle=True, batch_size=16)
-
- # create model
- model = nn.Sequential(
- nn.Linear(60, 60),
- nn.ReLU(),
- nn.Linear(60, 30),
- nn.ReLU(),
- nn.Linear(30, 1),
- nn.Sigmoid()
- )
-
- # Train the model
- n_epochs = 200
- loss_fn = nn.BCELoss()
- optimizer = optim.SGD(model.parameters(), lr=0.1)
- model.train()
- for epoch in range(n_epochs):
- for X_batch, y_batch in loader:
- y_pred = model(X_batch)
- loss = loss_fn(y_pred, y_batch)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
-
- # create one test tensor from the testset
- X_test, y_test = default_collate(testset)
- model.eval()
- y_pred = model(X_test)
- acc = (y_pred.round() == y_test).float().mean()
- acc = float(acc)
- print("Model accuracy: %.2f%%" % (acc*100))
Dataset
. 因此,在上面,您需要使用该
default_collate()
函数将数据集中的样本收集到张量中。
在这篇文章中,您学习了如何使用DataLoader
创建打乱的数据批次以及如何使用Dataset
提供数据样本。具体来说,您学到了:
DataLoader
作为向训练循环提供批量数据的便捷方式Dataset
生成数据样本Dataset
和DataLoader
生成批量数据以进行模型训练Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。