Pytorch深度学习代码记录(加载数据集)

epoch、Batch-size 、iteration

首先,在训练模型的时候,数据会被分成很多批次来处理。这里的批次应该就是batch吧,而batch size应该是指每个批次里的样本数量。比如,如果我有1000个训练样本,设置batch size为100,那么每个batch就有100个样本。这样的话,全部数据过一遍需要10个batch,也就是10次迭代(iteration),这样每个epoch完成一次所有数据的训练。每个epoch代表整个数据集被训练一次,而iteration是完成一个batch的前向和后向传播的次数。那如果我的数据集有1000个样本,batch size是100,那么一个epoch会有10个iteration,对吗?这样的话,完成一个epoch需要10次iteration,也就是每次iteration处理一个batch的数据,直到处理完整个数据集。那如果训练过程中,比如进行了5个epoch,每个epoch有10个iteration,那么总共有50次iteration,这时候模型总共看了5次整个数据集的数据,每次分10个batch处理。

另外,batch size的大小会影响训练效果。大的batch size可能会让训练速度更快,因为每次处理的数据更多,但可能会占用更多的内存。而小的batch size虽然每次更新更频繁,但可能需要更多的iteration来完成一个epoch,也可能带来更好的泛化能力,因为参数更新的次数更多,引入的噪声更多,可能避免陷入局部极小值。

torchvision

torchvision是PyTorch的扩展库,用于计算机视觉任务。主要功能模块有:datasets模块,里面包含常用的数据集,像MNIST、CIFAR、ImageNet等,还有预训练的模型,比如ResNet、VGG等。然后transforms模块,用于数据预处理,常见的操作如调整大小、标准化、数据增强等。接着utils模块,用于将多个图像合成一张图,方便可视化等等

Tensorboard

TensorBoard 是 深度学习实验的可视化工具包,它通过将训练过程中的各种数据转化为直观的图表,帮助开发者更好地理解、调试和优化模型,可在模型训练时进行训练过程的监控。

SummaryWriter是 与 TensorBoard 交互的核心类,用于将训练过程中的各种数据(标量、图像、模型结构等)写入日志文件,供 TensorBoard 可视化。

writer.add_scalar(tag,scalar_value,global_step=None,walltime=None )是 PyTorch 中记录标量数据的核心方法,用于将训练过程中的关键指标(如损失、准确率等)实时写入 TensorBoard 日志。

参数类型作用示例值
tagstring数据标识符(层级式命名推荐用 / 分隔)'Loss/Train'
scalar_valuefloat要记录的标量值0.23
global_stepint记录的步数/轮数(x轴坐标)epoch
walltimefloat可选,覆盖默认的时间戳(Unix时间)

time.time()

from torch.utils.tensorboard import SummaryWriter  #导入SummaryWriter类
import numpy as np
from PIL import Image

#创建写入器(日志保存到logs文件夹)
writer = SummaryWriter("logs")
image_path = "dataset/train/ants/0013035.jpg"
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL)

writer.add_image("test",img_array,1,dataformats='HWC')

for i in range(100):
    writer.add_scalar("y=2x",2*i,i)  #终端即可打开,tensorboard --logdir=logs --port=6007

#关闭写入器
writer.close()  # 确保所有数据写入磁盘

transforms 

transforms就是一个工具箱,里面有工具(类),图片可通过这些工具进行变换,得到想要的结果

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter("logs")
img_path = "dataset/train/ants/0013035.jpg"
img = Image.open(img_path)
print(img)

#ToTensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("Tensor_img",img_tensor)

#Normalize  归一化
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([6,3,2],[9,3,5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm,2)

writer.close()
#终端即可打开,tensorboard --logdir=logs --port=6007
import torchvision
from torch.utils.tensorboard import SummaryWriter

dataset_new_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToPILImage()
])
train_set = torchvision.datasets.CIFAR10(root = "./dataset_new",train=True,transform=dataset_new_transform,download=True)
test_set = torchvision.datasets.CIFAR10(root = "./dataset_new",train=False,transform=dataset_new_transform,download=True)

# print(test_set[0])
# print(test_set.classes)
#
# img,target = test_set[0]
# print(img)
# print(target)
# print(test_set.classes[target])
# img.show()
#
# print(test_set[0])

writer = SummaryWriter("p10")
for i in range(10):
    img, target = test_set[i]
    writer.add_image("test_set",img,i)

writer.close()

Dataset、Dataloader

1. Dataset:数据容器

  • 作用:存储样本数据和对应标签(类似字典,这样可以给每个数据都标上号,方便索引),提供统一的索引接口。Dataset是用来封装数据和标签的,用户需要继承这个类并实现__len__和__getitem__方法。继承Dataset的话,必须实现__getitem__和__len__这两个方法,否则在使用DataLoader的时候会出错。

  • 实现方式

    • 继承torch.utils.data.Dataset

    • 必须重写__len__(返回数据集大小)和__getitem__(通过索引获取样本)

    • Dataset 是一个抽象类,不能实例化对象,主要是用于构造我们的数据集。使用时必须进行重写,from 在torch.utils.data Dataset
      #(1)重写时,需要根据数据来进行构造__init__(self,filepath)
      #(2)__getitem__(self,index)用来让数据可以进行索引操作
      #(3)__len__(self)用来获取数据集的大小

      from torch.utils.data import Dataset  #导入Dataset类
      from PIL import Image
      import os
      
      class MyData(Dataset):  #继承Dataset类
          def __init__(self,root_dir,label_dir):  #初始化,为后面方法提供全局变量
              self.root_dir = root_dir  #数据集根目录(如"data/train")
              self.label_dir = label_dir  #标签对应子目录名(如"ants或bees")
              self.path =os.path.join(self.root_dir,self.label_dir)  #拼接完整路径(如"data/train/ants")
              self.img_path = os.listdir(self.path)  #获取该类别下所有图片文件名列表
      
          def __getitem__(self, index):
              img_name = self.img_path[index]  #根据索引获取单个文件名
              img_item_path =os.path.join(self.root_dir,self.label_dir,img_name)  #拼接图片完整路径
              img = Image.open(img_item_path)  #用PIL读取图片
              label = self.label_dir  #直接使用子目录名作为标签(如"ants")
              return img,label  #返回图像和标签
      
          def __len__(self):
              return len(self.img_path)  #返回该类别下的图片总数
              self.root_dir = root_dir  #数据集根目录(如"data/train")
              self.label_dir = label_dir  #标签对应子目录名(如"ants或bees")
              self.path =os.path.join(self.root_dir,self.label_dir)  #拼接完整路径(如"data/train/ants")
              self.img_path = os.listdir(self.path)  #获取该类别下所有图片文件名列表
      
          def __getitem__(self, index):
              img_name = self.img_path[index]  #根据索引获取单个文件名
              img_item_path =os.path.join(self.root_dir,self.label_dir,img_name)  #拼接图片完整路径
              img = Image.open(img_item_path)  #用PIL读取图片
              label = self.label_dir  #直接使用子目录名作为标签(如"ants")
              return img,label  #返回图像和标签
      
          def __len__(self):
              return len(self.img_path)  #返回该类别下的图片总数
      
      
      root_dir = "dataset/train"
      ants_label_dir = "ants"
      bees_label_dir = "bees"
      ants_dataset = MyData(root_dir,ants_label_dir)
      bees_dataset = MyData(root_dir,ants_label_dir)
      img,label = ants_dataset[23]
      img.show()

2. DataLoader:数据加载器

  • 作用:Dataloader负责把Dataset里的数据批量加载,可能还包含打乱顺序、多线程加载等功能。将Dataset包装为可迭代对象,支持:

    • 批量加载(Batching):batch_size

    • 乱序(Shuffling):shuffle=True

    • 多进程加速num_workers

    • 内存优化pin_memory=True(GPU加速时)

      import torchvision
      from torch.utils.data import DataLoader
      from torch.utils.tensorboard import SummaryWriter
      
      #准备的测试数据集
      test_data = torchvision.datasets.CIFAR10("./dataset_new",train = False,transform=torchvision.transforms.ToTensor())
      
      test_loader = DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)
      
      #测试数据集中第一张图片及target
      img,target = test_data[0]
      print(img.shape)
      print(target)
      
      writer = SummaryWriter("dataloader")
      for epoch in range(2):
          step = 0
          for data in test_loader:
              imgs,targets = data
              print(imgs.shape)
              print(targets)
              writer.add_images("Epoch:{}".format(epoch),imgs,step)
              step = step + 1
      
      writer.close()

总结

Dataset负责数据存储和单样本处理,Dataloader负责批量处理和迭代。简单来说,Dataset 负责告诉 PyTorch 数据在哪里、数据是什么,而 DataLoader 负责将这些数据打包成适合训练和测试的批次,并按需喂给模型。

import torch
import numpy as np
from torch.utils.data import Dataset
from torch.utils.data import DataLoader


#DataLoader 用来加载数据为mini-Batch ,支持Batch-size 的设置,shuffle支持数据的打乱顺序,#DataLoader 需要获取DataSet提供的索引[i]和len;用来帮助我们加载数据,比如说做shuffle(提高数据集#的随机性),batch_size,能拿出Mini-Batch进行训练。它帮我们自动完成这些工作。DataLoader可实例化对#象。

 
# prepare dataset
 
 
class DiabetesDataset(Dataset):
    def __init__(self, filepath):
        xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
        self.len = xy.shape[0] # shape(多少行,多少列)
        self.x_data = torch.from_numpy(xy[:, :-1])
        self.y_data = torch.from_numpy(xy[:, [-1]])
 
    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]
 
    def __len__(self):
        return self.len
 
 
dataset = DiabetesDataset('diabetes.csv')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=0) #num_workers 多线程
 
 
# design model using class
 
 
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        self.sigmoid = torch.nn.Sigmoid()
 
    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x
 
 
model = Model()
 
# construct loss and optimizer
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
 
# training cycle forward, backward, update
if __name__ == '__main__':
    for epoch in range(100):
        for i, data in enumerate(train_loader, 0): # train_loader 是先shuffle后mini_batch
            inputs, labels = data
            y_pred = model(inputs)
            loss = criterion(y_pred, labels)
            print(epoch, i, loss.item())
 
            optimizer.zero_grad()
            loss.backward()
 
            optimizer.step()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值