目录
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()