目錄
1 數據加載器
1.1 構建數據類
1.1.1 Dataset類
1.1.2 TensorDataset類
1.2 數據加載器
2 數據加載案例
2.1 加載csv數據集
2.2 加載圖片數據集
2.3 加載官方數據集
2.4 pytorch實現線性回歸
1 數據加載器
分數據集和加載器2個步驟~
1.1 構建數據類
1.1.1 Dataset類
Dataset是一個抽象類,是所有自定義數據集應該繼承的基類。它定義了數據集必須實現的方法。
必須實現的方法
-
__len__
: 返回數據集的大小 -
__getitem__
: 支持整數索引,返回對應的樣本
在 PyTorch 中,構建自定義數據加載類通常需要繼承 torch.utils.data.Dataset 并實現以下幾個方法:
- __init__ 方法 用于初始化數據集對象:通常在這里加載數據,或者定義如何從存儲中獲取數據的路徑和方法。
def __init__(self, data, labels):self.data = dataself.labels = labels
??????2.__len__ 方法 返回樣本數量:需要實現,以便 Dataloader加載器能夠知道數據集的大小。
def __len__(self):return len(self.data)
??????3.__getitem__ 方法 根據索引返回樣本:將從數據集中提取一個樣本,并可能對樣本進行預處理或變換。
def __getitem__(self, index):sample = self.data[index]label = self.labels[index]return sample, label
如果你需要進行更多的預處理或數據變換,可以在 __getitem__ 方法中添加額外的邏輯。
import torch
from torch.utils.data import Dataset,DataLoader,TensorDataset
from sklearn.datasets import make_regression
from torch import nn,optim
# 自定義數據集類
# 1.繼承dataset類
# 2.實現__init__方法,初始化外部的數據
# 3.實現__len__方法,用來返回數據集的長度
# 4.實現__getitem__方法,根據索引獲取對應位置的數據
class MyDataset(Dataset):def __init__(self,data,labels):self.data=dataself.labels=labelsdef __len__(self):return len(self.data)def __getitem__(self, index):sample=self.data[index]label=self.labels[ index]return sample,labeldef test01():x=torch.randn(100,20)y=torch.randn(100,1)dataset=MyDataset(x,y)print( dataset[0])if __name__=='__main__':test01()
1.1.2 TensorDataset類
TensorDataset
是Dataset
的一個簡單實現,它封裝了張量數據,適用于數據已經是張量形式的情況。
特點
-
簡單快捷:當數據已經是張量形式時,無需自定義Dataset類
-
多張量支持:可以接受多個張量作為輸入,按順序返回
-
索引一致:所有張量的第一個維度必須相同,表示樣本數量
def test03():torch.manual_seed(0)# 創建特征張量和標簽張量features = torch.randn(100, 5) # 100個樣本,每個樣本5個特征labels = torch.randint(0, 2, (100,)) # 100個二進制標簽# 創建TensorDatasetdataset = TensorDataset(features, labels)# 使用方式與自定義Dataset相同print(len(dataset)) # 輸出: 100print(dataset[0]) # 輸出: (tensor([...]), tensor(0))
1.2 數據加載器
在訓練或者驗證的時候,需要用到數據加載器批量的加載樣本。
DataLoader 是一個迭代器,用于從 Dataset 中批量加載數據。它的主要功能包括:
-
批量加載:將多個樣本組合成一個批次。
-
打亂數據:在每個 epoch 中隨機打亂數據順序。
-
多線程加載:使用多線程加速數據加載。
創建DataLoader:
# 創建 DataLoader
dataloader = DataLoader(dataset, # 數據集batch_size=10, # 批量大小shuffle=True, # 是否打亂數據num_workers=2 # 使用 2 個子進程加載數據
)
遍歷:
# 遍歷 DataLoader
# enumerate返回一個枚舉對象(iterator),生成由索引和值組成的元組
for batch_idx, (samples, labels) in enumerate(dataloader):print(f"Batch {batch_idx}:")print("Samples:", samples)print("Labels:", labels)
案例:
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader# 定義數據加載類
class CustomDataset(Dataset):#略......def test01():# 簡單的數據集準備data_x = torch.randn(666, 20, requires_grad=True, dtype=torch.float32)data_y = torch.randn(data_x.size(0), 1, dtype=torch.float32)dataset = CustomDataset(data_x, data_y)# 構建數據加載器data_loader = DataLoader(dataset, batch_size=8, shuffle=True)for i, (batch_x, batch_y) in enumerate(data_loader):print(batch_x, batch_y)breakif __name__ == "__main__":test01()
2 數據加載案例
通過一些數據集的加載案例,真正了解數據類及數據加載器。
2.1 加載csv數據集
import torch
from torch import nn
from torch.utils.data import TensorDataset,DataLoader
import pandas as pd
from torchvision import datasets,transformsdef build_csv_data(filepath):df=pd.read_csv(filepath)df.drop(["學號","姓名"],axis=1,inplace=True)# print(df.head())samples=df.iloc[...,:-1]labels=df.iloc[...,-1]# print(samples.head())# print(labels.head())samples=torch.tensor(samples.values)labels=torch.tensor(labels.values)# print(samples)# print(labels)return samples,labelsdef load_csv_data():filepath="./datasets/大數據答辯成績表.csv"samples,labels=build_csv_data(filepath)dataset=TensorDataset(samples,labels)dataloader=DataLoader(dataset=dataset,batch_size=1,shuffle=True)for sample,label in dataloader:print(sample)print(label)breakif __name__=="__main__":load_csv_data()
2.2 加載圖片數據集
import torch
from torch import nn
from torch.utils.data import TensorDataset,DataLoader
import pandas as pd
from torchvision import datasets,transformsdef load_img_data():path="./datasets/animals"transform=transforms.Compose([# 圖片縮放 把所有圖片縮放到同一尺寸transforms.Resize((224,224)),# 把PIL圖片或numpy數組轉為張量transforms.ToTensor(),])dataset=datasets.ImageFolder(root=path,transform=transform)dataloader=DataLoader(dataset=dataset,batch_size=4,shuffle=True)for x,y in dataloader:print(x.shape)print(x)print(y)breakif __name__=="__main__":load_img_data()
2.3 加載官方數據集
在 PyTorch 中官方提供了一些經典的數據集,如 CIFAR-10、MNIST、ImageNet 等,可以直接使用這些數據集進行訓練和測試。
數據集:Datasets — Torchvision 0.22 documentation
常見數據集:
-
MNIST: 手寫數字數據集,包含 60,000 張訓練圖像和 10,000 張測試圖像。
-
CIFAR10: 包含 10 個類別的 60,000 張 32x32 彩色圖像,每個類別 6,000 張圖像。
-
CIFAR100: 包含 100 個類別的 60,000 張 32x32 彩色圖像,每個類別 600 張圖像。
-
COCO: 通用對象識別數據集,包含超過 330,000 張圖像,涵蓋 80 個對象類別。
torchvision.transforms 和 torchvision.datasets 是 PyTorch 中處理計算機視覺任務的兩個核心模塊,它們為圖像數據的預處理和標準數據集的加載提供了強大支持。
transforms
模塊提供了一系列用于圖像預處理的工具,可以將多個變換組合成處理流水線。
datasets
模塊提供了多種常用計算機視覺數據集的接口,可以方便地下載和加載。
參考如下:
import torch
from torch.utils.data import Dataset, DataLoader
import torchvision
from torchvision import transforms, datasetsdef test():transform = transforms.Compose([transforms.ToTensor(),])# 訓練數據集data_train = datasets.MNIST(root="./data",train=True,download=True,transform=transform,)trainloader = DataLoader(data_train, batch_size=8, shuffle=True)for x, y in trainloader:print(x.shape)print(y)break# 測試數據集data_test = datasets.MNIST(root="./data",train=False,download=True,transform=transform,)testloader = DataLoader(data_test, batch_size=8, shuffle=True)for x, y in testloader:print(x.shape)print(y)breakdef test006():transform = transforms.Compose([transforms.ToTensor(),])# 訓練數據集data_train = datasets.CIFAR10(root="./data",train=True,download=True,transform=transform,)trainloader = DataLoader(data_train, batch_size=4, shuffle=True, num_workers=2)for x, y in trainloader:print(x.shape)print(y)break# 測試數據集data_test = datasets.CIFAR10(root="./data",train=False,download=True,transform=transform,)testloader = DataLoader(data_test, batch_size=4, shuffle=False, num_workers=2)for x, y in testloader:print(x.shape)print(y)breakif __name__ == "__main__":test()test006()
2.4 pytorch實現線性回歸
import torch
from torch.utils.data import Dataset,DataLoader,TensorDataset
from sklearn.datasets import make_regression
from torch import nn,optim# pytorch實現線性回歸
def build_data(in_features,out_features):bias=14.5# 生成的數據需要轉換成tensorx,y,coef=make_regression(n_samples=1000,n_features=in_features,n_targets=out_features,coef=True,bias=bias,noise=0.1,random_state=42)x=torch.tensor(x,dtype=torch.float32)y=torch.tensor(y,dtype=torch.float32).view(-1,1) # 注意要把y轉換成二維數組(本來是一維) 否則會報警告coef=torch.tensor(coef,dtype=torch.float32)bias=torch.tensor(bias,dtype=torch.float32)return x,y,coef,biasdef train():# 數據準備in_features=10out_features=1x,y,coef,bias=build_data(in_features,out_features)dataset=TensorDataset(x,y)dataloader=DataLoader(dataset=dataset,batch_size=100,shuffle=True)# 定義網絡模型model=nn.Linear(in_features,out_features)# 定義損失函數criterion=nn.MSELoss()# 優化器opt=optim.SGD(model.parameters(),lr=0.1)epochs=20for epoch in range(epochs):for tx,ty in dataloader:y_pred=model(tx)loss=criterion(y_pred,ty)opt.zero_grad()loss.backward()opt.step()print(f'epoch:{epoch},loss:{loss.item()}')# detach()、data:作用是將計算圖中的weight參數值獲取出來print(f"真實權重:{coef.numpy()},訓練權重:{model.weight.detach().numpy()}") # datach()相當于把weight從計算圖中抽離出來print(f"真實偏置:{bias},訓練偏置:{model.bias.item()}")if __name__=='__main__':train()