完整模型训练套路 试写 以CIFAR10分类数据集为例

思路步骤:  

第一步准备数据集:(训练集,测试集)

import torchvision

Train_dataset = torchvision.datasets.CIFAR10("./data",True,transform=torchvision.transforms.ToTensor())
Test_Dataset =torchvision.datasets.CIFAR10("./data",False,transform=torchvision.transforms.ToTensor())

 transform=torchvision.transforms.ToTensor() 将数据集图片转换为Tensor数据类型

第二步查询数据集长度:(len)

###第二步查询数据集长度
Train_length = len(Train_dataset)
Test_length = len(Test_Dataset)
print(f"训练集长度为{Train_length}")
print((f"测试集长度为{Test_length}"))

 

第三步加载数据集(DataLoader)

##第三步加载数据集
Train_load = DataLoader(Train_dataset,64,True)
Test_load = DataLoader(Test_Dataset,64,True)

第四步搭建神经网络,将神经网络放入单独的一个python文件中,测试网络正确性

class Tudui(nn.Module):

 nn.Module 是所有神经网络模块的基类,用于创建自定义网络。

通过继承nn.Module,模型可以使用PyTorch提供的各种功能和方法,如参数管理、设备移动等。 

遵循这种结构的模型可以轻松地与PyTorch的其他组件(如优化器、损失函数等)集成 

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()

  • super() 主要用于调用父类(超类)的方法。
nn.Conv2d(3,32,padding=2,stride=1)

输入通道为3,输出通道为32,高宽不变padding = [(卷积核数-1 )/2]

 对应神经网络部分:

        self.model = nn.Sequential(
            nn.Conv2d(3,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,64,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4,64),
            nn.Linear(64,10),

        )

具体搞清楚python中 self.model写法  不能用self 直接替代的原因

###第四步搭建神经网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,64,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4,64),
            nn.Linear(64,10),

        )

    def forward(self,x):
        x = self.model(x)
        return  x

测试网络的正确性 :

input = torch.ones(64,3,32,32)

创建一个四维张量,表示一批图像数据 ,参数batch_size,channels,H,W

if __name__ == '__main__':
    tudui = Tudui()
    input = torch.ones(64,3,32,32)
    output = tudui(input)
    print(output.shape)

结果: 

第五步创建网络模型

###创建网络模型
tudui = Tudui()

第六步创建损失函数:

loss_fn = nn.CrossEntropyLoss()

第七步创建优化器:

##创建优化器
learning_rate =0.01
optimize = torch.optim.SGD(tudui.parameters(),lr=learning_rate)

第八步设置训练参数,开始训练: 

起始参数设置:

train_step = 0###起始训练次数
test_step = 0###起始测试次数
epoch = 10 ####训练十轮

训练开始 :从train_load读取训练集

 for data in Train_load:####训练开始
        imgs,targets = data

将图片输入至模型中得到输出 ,并利用损失函数计算Loss

 output = tudui(imgs)
loss = loss_fn(output,targets)

 优化器梯度清零:

  1. 防止梯度累积:

    • PyTorch 默认累积梯度。不清理会导致梯度在多个批次间累加。
  2. 确保每批次独立:

    每个批次的梯度应该只反映当前批次的计算结果。
        optimize.zero_grad()
        loss.backward()
        optimize.step()
        train_step+=1
        print(f"训练次数为{train_step},loss值{loss}")

测试开始:从test_load读取测试集

    test_loss = 0
    with torch.no_grad():
        for data in Test_load:
            imgs,targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)
            test_loss = test_loss+loss
    print(f"整体测试集上的loss为{test_loss}")

注意写法 test_loss是普通数据类型,而loss为tensor数据类型,loss.item() 返回一个Python标量(如float),而不是PyTorch张量.

test_loss = test_loss+loss.item()

 添加Tensorboard:

生成日志路径:

writer =SummaryWriter("./logs_train")

在训练集后添加相关数据

writer.add_scalar("训练loss",loss,train_step)

在测试集添加相关数据

writer.add_scalar("测试loss", test_loss, test_step)

 训练集50000 测试集10000。每一个epoch,batch_size= 64 ,需要训练781次

生成模型的保存:

    torch.save(tudui.state_dict(), f"tudui_model_epoch_{i + 1}.pth")
    print(f"第{i + 1}轮模型已保存到 tudui_model_epoch_{i + 1}.pth")

argmax()的使用 :

import torch
outputs =torch.tensor([[0.1,0.2],
             [0.5,0.3]])
print(outputs.argmax(1))
print(outputs.argmax(0))
  • argmax(1) 返回每行的最大值索引。
  • argmax(0) 返回每列的最大值索引。

 计算预测值与目标值相等的个数

outputs =torch.tensor([[0.1,0.2],
             [0.5,0.3]])
preds = outputs.argmax(1)
targets = torch.tensor([1,0])##[0,1],[1,1],[1,0]
print((preds==targets).sum())

 输出个数为2

通过argmax()进行代码优化 计算出整体ACC(正确率) :

 accuracy =((outputs.argmax(1) == targets).sum())
  • outputs.argmax(1) 找出每个样本预测概率最高的类别。
  • (outputs.argmax(1) == targets) 比较预测类别和真实标签,得到一个布尔张量。
  • .sum() 计算这个布尔张量的总和,即正确预测的数量。
  • total_accuracy = total_accuracy + accuracy 累加每个批次的正确预测数。
  • 最后,用 total_accuracy / Test_length 计算整体准确率。

tudui.train() 和tudui.eval()作用解析

tudui.train()在训练部分:

tudui.train(true) 这只对某些模块有影响。如果它们受到影响,请参阅特定模块的文档,了解它们在培训/评估模式下的行为细节,例如Dropout、BatchNorm等。

tudui.eval()在测试部分同理 

使用GPU训练:

GPU训练 只需要在原始CPU代码中 对:网络模型,数据(输入,标注),损失函数调用cuda 

就可以使用CPU训练

问题:网络模型和损失函数调用cuda 不需要赋值回去

而数据需要赋值回去 

        imgs = imgs.cuda()
        targets = targets.cuda()

优化写法一:GPU 与CPU 可以同时运行

if torch.cuda.is_available():
    loss_fn.cuda()

优化写法二:定义训练的设备

device = torch.device("cuda")          
imgs = imgs.to(device)
targets = targets.to(device)

优化写法:

device = torch.device("cuda"if torch.cuda.is_available()else"cpu")

GPU训练测试代码:

###第一步
import torch
import torchvision
from torch import nn
from torch.utils.tensorboard import SummaryWriter

from model import *
from torch.utils.data import DataLoader
writer =SummaryWriter("./logs_train")
Train_dataset = torchvision.datasets.CIFAR10("./data",True,transform=torchvision.transforms.ToTensor(),download=True)
Test_Dataset =torchvision.datasets.CIFAR10("./data",False,transform=torchvision.transforms.ToTensor(),download=True)
###定义训练的设备
device = torch.device("cuda"if torch.cuda.is_available()else"cpu")
###第二步查询数据集长度
Train_length = len(Train_dataset)
Test_length = len(Test_Dataset)
print(f"训练集长度为{Train_length}")
print((f"测试集长度为{Test_length}"))

##第三步加载数据集
Train_load = DataLoader(Train_dataset,64,True)
Test_load = DataLoader(Test_Dataset,64,True)

###第四步已保存

###创建网络模型
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,64,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4,64),
            nn.Linear(64,10),

        )

    def forward(self,x):
        x = self.model(x)
        return  x
tudui = Tudui()
tudui.to(device)
###创建损失函数

loss_fn = nn.CrossEntropyLoss()
loss_fn.to(device)
##创建优化器
learning_rate =0.01
optimize = torch.optim.SGD(tudui.parameters(),lr=learning_rate)
###设置参数
train_step = 0###起始训练次数
test_step = 0###起始测试次数
epoch = 30 ####训练十轮
for i in range(epoch):
    print(f"-------目前是第{i+1}轮训练-----------")
    for data in Train_load:####训练开始
        imgs,targets = data
        imgs = imgs.to(device)
        targets = targets.to(device)
        outputs = tudui(imgs)
        loss = loss_fn(outputs,targets)
        ###优化器优化模型
        optimize.zero_grad()
        loss.backward()
        optimize.step()
        train_step+=1
        if train_step%100 ==0:
            print(f"训练次数为{train_step},loss值{loss}")
            writer.add_scalar("训练loss",loss,train_step)
        ####测试步骤
    total_accuracy = 0  ###整体准确率为0
    test_loss = 0
    with torch.no_grad():
        for data in Test_load:
            imgs,targets = data
            imgs = imgs.to(device)
            targets = targets.to(device)
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)
            test_loss = test_loss+loss.item()
            accuracy =((outputs.argmax(1) == targets).sum())
            total_accuracy = total_accuracy+accuracy
    print(f"整体测试集上的loss为{test_loss}")
    print((f"整体测试集上的准确率为{total_accuracy/Test_length}"))
    writer.add_scalar("测试loss", test_loss, test_step)
    test_step+=1


    ###模型保存
    torch.save(tudui, f"tudui_model_epoch_{i + 1}.pth")
    print(f"第{i + 1}轮模型已保存到 tudui_model_epoch_{i + 1}.pth")


writer.close()

 

利用训练的好的模型进行验证:

import torch
import torchvision
from PIL import  Image
from torch import nn
###定义训练的设备
device = torch.device("cuda"if torch.cuda.is_available()else"cpu")
print(f"当前使用设备为: {device}")
image_path = "./imgs/horse.jpg."
image = Image.open(image_path)
print(image)
image =image.convert('RGB')
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                           torchvision.transforms.ToTensor()])
image = transform(image)
print(image.shape)


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,32,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Conv2d(32,64,padding=2,stride=1,kernel_size=5),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4,64),
            nn.Linear(64,10),

        )

    def forward(self,x):
        x = self.model(x)
        return  x

model = torch.load("tudui_model_epoch_10.pth")
model = model.to(device)
image = image.to(device)
print(model)
image = torch.reshape(image,(1,3,32,32))
model.eval()
with torch.no_grad():
    output = model(image)
print(output)
print(output.argmax(1))

 

验证成功为一匹马:

要注意输入图片与训练好的模型 在CPU与GPU上的部署,及时调整代码 

 


  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值