第七章 完整的模型训练

模型框架与测试

建一个名为model的py文件用于保存模型框架

python 复制代码
import torch
from torch import nn

class Myx(nn.Module):
    def __init__(self):
        super().__init__()
        self.model=nn.Sequential(
            nn.Conv2d(3,32,5,padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32,32,5,padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32,64,5,padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(1024,64),
            nn.Linear(64,10)
        )

    def forward(self, x):
        x=self.model(x)
        return x
#写个测试试一下代码是否成功
if __name__ == '__main__':
    myx=Myx()
    input=torch.ones((64,3,32,32))
    output=myx(input)
    print(output.shape)

使用if name == "main": 可以让你的Python文件既可以作为脚本直接运行,也可以作为模块被其他文件导入而不执行特定代码块

完整模型训练套路

argmax函数

作用

argmax()可以按照一定方向得到最大值的索引,在分类的时候将输出由概率值转为概率最大值的下标

实例

python 复制代码
import torch
output=torch.tensor([[0.2,0.4],
                    [0.3,0.5]])
preds=output.argmax(1)#参数为1一行为一组,参数为0一列为一组
targets=torch.tensor([0,1])#真实标签的下标
print(preds==targets)#转换为bool值,true为预测正确
python 复制代码
tensor([False,  True])

预测正确的数量:

python 复制代码
preds_true_amount=(preds==targets).sum()
print(preds_true_amount)
python 复制代码
tensor(1)

实例

python 复制代码
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torch.utils.data import DataLoader
from model import *

#准备数据集
train_data=torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transforms.ToTensor())

#查看数据集长度(照片数量)
train_data_size=len(train_data)
test_data_size=len(test_data)
print(f"训练数据集的长度为:{train_data_size}")
print(f"测试数据集的长度为:{test_data_size}")

#利用dataloader进行数据集加载
train_dataloader=DataLoader(train_data, batch_size=64)
test_dataloader=DataLoader(test_data, batch_size=64)

#搭建神经网络
#将搭建好的网络单独存放在mode.py下并测试
#创建网络模型
myx=Myx()
#损失函数
loss_function=nn.CrossEntropyLoss()
#优化器
learning_rate=0.001
optimizer=torch.optim.SGD(myx.parameters(), lr=learning_rate)
#设置训练网络的参数
total_train_step=0#训练次数
total_test_step=0#测试次数
epoch=10#训练轮数
#训练开始
myx.train()#将网络设置为训练状态
for i in range(epoch):
    print(f"--------------------第{i+1}轮训练开始-----------------------")
    for data in train_dataloader:#
        imgs,targets=data
        res=myx(imgs)#得到预测值
        loss=loss_function(res,targets)#预测值与真实值比较得到loss
        #优化器优化模型
        optimizer.zero_grad()#梯度清零
        loss.backward()#通过loss反向传播得到梯度
        optimizer.step()#优化器通过梯度优化参数
        total_train_step+=1
        print(f"-----------------训练为第{total_train_step}次,loss为{loss.item()}-----------------")#使用.item()可以获得数据中的内容忽视其格式

    #测试步骤
    myx.eval()#将网络设置为测试状态
    total_test_loss=0
    total_accuarcy=0
    with torch.no_grad():#测试的时候不需要对梯度进行调整
        for data in test_dataloader:
            imgs,targets=data
            res=myx(imgs)
            loss=loss_function(res,targets)
            total_test_loss+=loss.item()
            accuarcy=(res.argmax(1)==targets).sum()#预测正确的个数
            total_accuarcy+=accuarcy
    print(f"整体测试集上的loss:{total_test_loss}")
    print(f"整体测试集上的正确率:{total_accuarcy}/{test_data_size}")

    #保存每一轮训练结果
    torch.save(myx,f"myx_model_{i}.pth")
    print("模型已保存")

利用GPU训练

方法一------.cuda()

用gpu训练的第一种方法,就是把之前的模型、损失函数和数据通过**调用.cuda()**全都转移到cuda上进行

python 复制代码
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torch.utils.data import DataLoader
from model import *
train_data=torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transforms.ToTensor())
train_data_size=len(train_data)
test_data_size=len(test_data)
print(f"训练数据集的长度为:{train_data_size}")
print(f"训练数据集的长度为:{test_data_size}")
train_dataloader=DataLoader(train_data, batch_size=64)
test_dataloader=DataLoader(test_data, batch_size=64)
myx=Myx()

#模型转移到cuda上
myx=myx.cuda()

loss_function=nn.CrossEntropyLoss()
#损失函数转移到cuda上
loss_function=loss_function.cuda()

learning_rate=0.001
optimizer=torch.optim.SGD(myx.parameters(), lr=learning_rate)
total_train_step=0
total_test_step=0
epoch=10
myx.train()
for i in range(epoch):
    print(f"--------------------第{i+1}轮训练开始-----------------------")
    for data in train_dataloader:
        imgs,targets=data

        #将训练数据转移到cuda上
        imgs=imgs.cuda()
        targets=targets.cuda()

        res=myx(imgs)
        loss=loss_function(res,targets)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step+=1
        print(f"-----------------训练为第{total_train_step}次,loss为{loss.item()}-----------------")

    myx.eval()
    total_test_loss=0
    total_accuarcy=0
    with torch.no_grad():
        for data in test_dataloader:
            imgs,targets=data

            # 将测试数据转移到cuda上
            imgs = imgs.cuda()
            targets = targets.cuda()

            res=myx(imgs)
            loss=loss_function(res,targets)
            total_test_loss+=loss.item()
            accuarcy=(res.argmax(1)==targets).sum()
            total_accuarcy+=accuarcy
    print(f"整体测试集上的loss:{total_test_loss}")
    print(f"整体测试集上的正确率:{total_accuarcy}/{test_data_size}")

主要有四步,模型-损失函数-训练数据-测试数据,全部转移到cuda上

方法二------torch.device()

用gpu训练的第二种方法,使用**.to(device)转移到torch.device()**上,这样只需在前面修改device()中的内容就可以更改用cpu还是gpu进行训练,更常用

python 复制代码
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torch.utils.data import DataLoader
from model import *

#定义训练用的设备
device=torch.device("cpu")

train_data=torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transforms.ToTensor())
train_data_size=len(train_data)
test_data_size=len(test_data)
print(f"训练数据集的长度为:{train_data_size}")
print(f"训练数据集的长度为:{test_data_size}")
train_dataloader=DataLoader(train_data, batch_size=64)
test_dataloader=DataLoader(test_data, batch_size=64)
myx=Myx()

#将模型转移到device上
myx=myx.to(device)

loss_function=nn.CrossEntropyLoss()

#将损失函数转移到device上
loss_function=loss_function.to(device)

learning_rate=0.001
optimizer=torch.optim.SGD(myx.parameters(), lr=learning_rate)
total_train_step=0
total_test_step=0
epoch=10
myx.train()
for i in range(epoch):
    print(f"--------------------第{i+1}轮训练开始-----------------------")
    for data in train_dataloader:
        imgs,targets=data

        #将训练数据转移到device上
        imgs=imgs.to(device)
        targets=targets.to(device)

        res=myx(imgs)
        loss=loss_function(res,targets)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step+=1
        print(f"-----------------训练为第{total_train_step}次,loss为{loss.item()}-----------------")
    myx.eval()
    total_test_loss=0
    total_accuarcy=0
    with torch.no_grad():
        for data in test_dataloader:
            imgs,targets=data

            # 将测试数据转移到device上
            imgs = imgs.to(device)
            targets = targets.to(device)

            res=myx(imgs)
            loss=loss_function(res,targets)
            total_test_loss+=loss.item()
            accuarcy=(res.argmax(1)==targets).sum()
            total_accuarcy+=accuarcy
    print(f"整体测试集上的loss:{total_test_loss}")
    print(f"整体测试集上的正确率:{total_accuarcy}/{test_data_size}")

也要分四步,模型-损失函数-训练数据-测试数据

相比与第一种方法,第二种方法在修改时更加方便

使用demo进行测试

python 复制代码
#得到训练后的模型后对模型进行测试也叫demo
import torch
import torchvision
from PIL import Image

image_path= "/image/img.png"
image=Image.open(image_path)
image=image.convert('RGB')#将png图片转换为rgb三通道
transform=torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                          torchvision.transforms.ToTensor()])#Resize参数元组(高,宽),compose中需要用列表[]
image=transform(image)
model=torch.load("/myx_model_0.pth", map_location=torch.device('cpu'))#如果是在gpu上运行得到的模型需要加上这句话
image=torch.reshape(image,(1,3,32,32))#加上batch_size为1

model.eval()#将模型改为测试状态
with torch.no_grad():#不改变grad
    res=model(image)
print(res.argmax(1))#输出可能性最大的标签索引

将保存好的模型随便找几张图输出,看一下结果与预期是否相符

相关推荐
codists1 分钟前
以 Core i9-13900HX 实例讲解CPU概念:物理CPU,内核,逻辑CPU
python
光头程序员5 分钟前
学习笔记——vite 打包构建优化之tree shaking
笔记·学习
Salt_072811 分钟前
DAY25 奇异值SVD分解
python·算法·机器学习
AI即插即用12 分钟前
即插即用系列 | CVPR 2024 ABC-Attention:基于双线性相关注意力的红外小目标检测
图像处理·人工智能·深度学习·目标检测·计算机视觉·cnn·视觉检测
AI即插即用13 分钟前
即插即用系列 | WACV 2025 SvANet:专为极小目标(<1%)设计的尺度变化注意力网络,医学图像分割新SOTA!
人工智能·深度学习·神经网络·目标检测·计算机视觉·cnn·视觉检测
秋邱17 分钟前
AR + 离线 AI 实战:YOLOv9+TensorFlow Lite 实现移动端垃圾分类识别
开发语言·前端·数据库·人工智能·python·html
程序员杰哥20 分钟前
UI自动化测试框架:PO 模式+数据驱动
自动化测试·软件测试·python·selenium·测试工具·ui·测试用例
源于花海25 分钟前
昇腾Catlass的算子优化:Transformer中小批量矩阵乘法优化与性能提升实践
深度学习
走在路上的菜鸟29 分钟前
Android学Dart学习笔记第十一节 分支
android·笔记·学习·flutter
源于花海31 分钟前
PyTorch模型轻松迁移昇腾平台:BERT优化与RoPE自定义算子实战
深度学习