如何在PyTorch中使用DataLoader?


PyTorch是一個流行的開源機器學習庫。資料科學家、研究人員和開發者廣泛使用這個庫來開發AI/ML產品。PyTorch最重要的功能之一是DataLoader類。這個類有助於高效地載入和批處理神經網路訓練的資料。本文將教我們如何在PyTorch中使用DataLoader。

在PyTorch中使用DataLoader

我們可以遵循以下基本規則,使用PyTorch庫在Python中執行資料載入操作:

  • 資料準備 - 建立一個自定義的Random Dataset類,生成所需大小的隨機資料集。使用DataLoader建立資料批次,指定批次大小並啟用資料混洗。

  • 神經網路定義 - 定義一個神經網路類Net,包含兩個全連線層和一個啟用函式。根據每層所需的單元數量自定義架構。

  • 初始化和最佳化 - 例項化Net類,設定均方誤差(MSE)損失準則,並將最佳化器初始化為具有所需學習率的隨機梯度下降(SGD)。

  • 訓練迴圈 - 迭代DataLoader,進行所需數量的輪次訓練。對於每一批資料,計算網路輸出,計算損失,反向傳播梯度,更新權重,並跟蹤執行損失。

示例

以下程式碼定義了一個簡單的神經網路和一個包含1000個數據點(每個資料點有10個特徵)的隨機資料集。然後,它使用批次大小為32並對資料進行混洗的DataLoader從資料集中建立DataLoader。神經網路使用具有均方誤差損失函式的隨機梯度下降進行訓練。訓練迴圈迭代DataLoader進行10個輪次訓練,計算每一批資料的損失,反向傳播梯度,並更新網路權重。每10個批次列印一次執行損失,以監控訓練進度。

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
class RandomDataset(Dataset):
    def __init__(self, size):
        self.data = torch.randn(size, 10)
    def __len__(self):
        return len(self.data)
    def __getitem__(self, index):
        return self.data[index]
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(10, 5)
        self.fc2 = nn.Linear(5, 1)

    def forward(self, x):
        x = self.fc1(x)
        x = nn.functional.relu(x)
        x = self.fc2(x)
        return x
dataset = RandomDataset(1000)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
net = Net()
criterion = nn.MSELoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)
for epoch in range(10):
    running_loss = 0.0
    for i, data in enumerate(dataloader, 0):
        inputs = data
        labels = torch.rand((data.shape[0], 1))
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
        if i % 10 == 9:
            print(f"[Epoch {epoch + 1}, Batch {i + 1}] loss: {running_loss / 10}")
            running_loss = 0.0

輸出

[Epoch 1, Batch 10] loss: 0.25439725518226625
[Epoch 1, Batch 20] loss: 0.18304144889116286
[Epoch 1, Batch 30] loss: 0.1451663628220558
[Epoch 2, Batch 10] loss: 0.12896266356110572
[Epoch 2, Batch 20] loss: 0.11783223450183869
………………………………………………………..
[Epoch 10, Batch 30] loss: 0.09491728842258454

資料取樣和加權取樣

資料取樣是指僅選擇資料的子集進行執行。當大量資料無法放入RAM時,這在機器學習和資料分析中至關重要。取樣有助於分批進行訓練、測試和驗證。加權取樣是取樣的一種變體,我們為資料點定義一些權重。這考慮到了對預測影響更大的資料點具有更大的意義。

語法

weighted_sampler = WeightedRandomSampler(“weights in the form of array like
objects”, num_samples=len(dataset), other parameters…)
loader = DataLoader(dataset, batch_size=batch_size,
sampler=weighted_sampler, other parameters......)

這裡我們需要將權重定義為列表或類似陣列的物件;Weighted Random Sampler然後建立取樣器。然後我們需要將資料集傳遞給DataLoader物件。我們需要使用引數“sampler”進行加權取樣。

示例

我們在下面的示例中使用DataLoader和Weighted Random Sampler實現了加權取樣。我們將資料集和batch_size=32傳遞給DataLoader物件。這意味著一次處理32個數據樣本。我們使用Weighted Random Sampler方法為樣本賦予權重。由於我們將replacement=True,資料點可以包含在多個批次中。

import torch
from torch.utils.data import Dataset, DataLoader, WeightedRandomSampler
class CustomDataset(Dataset):
    def __init__(self):
        self.data = torch.randn((1000, 3, 32, 32))
        self.labels = torch.randint(0, 10, (1000,))
    def __len__(self):
        return len(self.data)
    def __getitem__(self, index):
        data_sample = self.data[index]
        label = self.labels[index]
        return data_sample, label
dataset = CustomDataset()
weights = torch.where(dataset.labels == 0, torch.tensor(2.0), torch.tensor(1.0))
sampler = WeightedRandomSampler(weights, len(dataset), replacement=True)
dataloader = DataLoader(dataset, batch_size=32, sampler=sampler)
for batch_data, batch_labels in dataloader:
    print(batch_data.shape, batch_labels.shape) 

輸出

torch.Size([32, 3, 32, 32]) torch.Size([32])
torch.Size([32, 3, 32, 32]) torch.Size([32])
..................................................
torch.Size([32, 3, 32, 32]) torch.Size([32])
torch.Size([32, 3, 32, 32]) torch.Size([32])
torch.Size([8, 3, 32, 32]) torch.Size([8])

多執行緒資料載入

多執行緒載入是一個加速資料載入和預處理過程的方法。此技術旨在跨裝置在多個執行緒中並行化資料載入操作,使其能夠更快地處理執行。我們可以使用num_workers引數在PyTorch中啟用此功能。該引數以整數形式接受要使用的執行緒數。

語法

dataloader = DataLoader( num_workers=<number of workers>, other parameters)

這裡的num_workers是執行期間可以發生子程序的數量。將num_works設定為可用的CPU執行緒數很常見。如果設定為-1,它將利用所有可用的CPU核心。

示例

在下面的程式碼中,我們將num_workers設定為2,這意味著資料載入和預處理過程將並行地在2個執行緒中發生。我們將batch_size保持為32,shuffle=True(混洗將在建立批次之前發生)。

import torch
from torch.utils.data import Dataset, DataLoader

class CustomDataset(Dataset):
    def __init__(self, num_samples):
        self.data = torch.randn((num_samples, 3, 64, 64))
        self.labels = torch.randint(0, 10, (num_samples,))

    def __len__(self):
        return len(self.data)

    def __getitem__(self, index):
        data_sample = self.data[index]
        label = self.labels[index]
        return data_sample, label
dataset = CustomDataset(num_samples=3000)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=2)
for batch_data, batch_labels in dataloader:
    print("Batch data shape:", batch_data.shape)
    print("Batch labels shape:", batch_labels.shape)

輸出

Batch data shape: torch.Size([32, 3, 64, 64])
Batch labels shape: torch.Size([32])
Batch data shape: torch.Size([32, 3, 64, 64])
.......................................................
Batch data shape: torch.Size([24, 3, 64, 64])
Batch labels shape: torch.Size([24])

混洗和批次大小

顧名思義,混洗是指隨機重新排序資料點。這有幾個優點,包括消除偏差。預期的是,在混洗資料後,資料點會更加均勻,從而導致模型更好地微調。相反,批次大小是指對資料點進行分組並一次執行它們。這很重要,因為大量資料有時可能無法完全放入記憶體。

語法

dataloader = DataLoader(dataset, batch_size=<set a number>,
shuffle=<Boolean True or False>, other parameters...)

這裡資料集是我們需要設定批次大小並對其進行混洗的資料。批次大小以整數形式接受引數。Shuffle接受布林值True和False作為引數。如果設定為True,則進行混洗;如果設定為False,則不進行混洗。

示例

在下面的示例中,我們將兩個重要的引數傳遞給DataLoader類,即batch_size和shuffle。我們將batch_size設定為128,這意味著將同時執行128個數據點。shuffle=True表示每次執行之前都會進行混洗。如果設定為False,則不會發生混洗,我們可能會遇到略微有偏差的模型。

import torch
from torch.utils.data import Dataset, DataLoader

class CustomDataset(Dataset):
    def __init__(self, num_samples):
        self.data = torch.randn((num_samples, 3, 32, 32))
        self.labels = torch.randint(0, 10, (num_samples,))
    def __len__(self):
        return len(self.data)
    def __getitem__(self, index):
        data_sample = self.data[index]
        label = self.labels[index]
        return data_sample, label
dataset = CustomDataset(num_samples=1000)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=2)
for batch_data, batch_labels in dataloader:
    print("Batch data shape:", batch_data.shape)
    print("Batch labels shape:", batch_labels.shape)

輸出

Batch data shape: torch.Size([128, 3, 32, 32])
Batch labels shape: torch.Size([128])
......................................................
Batch data shape: torch.Size([104, 3, 32, 32])
Batch labels shape: torch.Size([104])

結論

在本文中,我們討論了在PyTorch中使用DataLoader。我們可以稍後處理這些資料來訓練神經網路。當我們在任何現有模型上訓練資料時,這些類非常有用。這有助於我們節省時間並獲得良好的結果,因為多個開發人員為模型、開源社群等做出了貢獻。同樣重要的是要理解,不同的模型可能需要不同的超引數。因此,這取決於可用的資源和資料的特性,應該選擇哪些引數。

更新於:2023年7月28日

瀏覽量:200

啟動你的職業生涯

透過完成課程獲得認證

開始學習
廣告
© . All rights reserved.