Pytorch学习 day13(完整的模型训练步骤)

步骤一:定义神经网络结构

  • 注意:由于一次batch_size的大小为64,表示一次放入64张图片,且Flatten()只会对单张图片的全部通道做拉直操作,也就是不会将batch_size合并,但是一张图片有3个通道,在Maxpool层之后,有64个通道,且每个通道的大小为4*4,所以Flatten()的输入为[64, 64, 4, 4]那么Flatten()的输出就为[64, 1024], 1024 = 64 * 4 * 4
  • 注意:通过ones()函数创建一个全1的tensor,作为输入数据,我们只需要指定输入数据的形状即可,我们可以通过ones()创建的简单输入,来检测网络的结构是否正确,()内写序列
  • 代码如下:
# 搭建神经网络
import torch
from torch import nnclass Tudui(nn.Module):def __init__(self):super().__init__()self.model = nn.Sequential(nn.Conv2d(3,32,5,1,2),nn.MaxPool2d(2),nn.Conv2d(32,32,5,1, 2),nn.MaxPool2d(2),nn.Conv2d(32,64,5,1,2),nn.MaxPool2d(2),# 由于一次batch_size的大小为64,表示一次放入64张图片,且Flatten()只会对单张图片的全部通道做拉直操作,也就是不会将batch_size合并# 但是一张图片有3个通道,在Maxpool层之后,有64个通道,且每个通道的大小为4*4,所以Flatten()的输入为[64, 64, 4, 4]# 那么Flatten()的输出就为[64, 1024], 1024 = 64 * 4 * 4nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10))def forward(self, x):x = self.model(x)return xif __name__ == '__main__':tudui = Tudui()# 通过ones()函数创建一个全1的tensor,作为输入数据,我们只需要指定输入数据的形状即可,# 我们可以通过ones()创建的简单输入,来检测网络的结构是否正确,()内写序列input = torch.ones((64, 3, 32, 32))output = tudui(input)print(output.shape)

步骤二:导入数据集,载入数据,创建网络模型,设置训练参数

  • 注意:有些代码的模型结构在module.py文件夹内,需要我们手动导包后才能创建实例
  • 注意: 先进行梯度清零,之后再反向传播、更新参数
  • 注意:优化器实例 . 梯度清零,损失实例 . 反向传播,优化器实例 . 更新参数
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import transformsfrom learn_pytorch.module import Tuduitrain_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=False, transform=transforms.ToTensor(), download=True)# 获得训练数据集和测试数据集的大小
train_dataset_size = len(train_dataset)
test_dataset_size = len(test_dataset)
print('训练数据集大小:', train_dataset_size)
print('测试数据集大小:', test_dataset_size)# 加载训练数据集和测试数据集
train_loader = DataLoader(dataset=train_dataset, batch_size=64)
test_loader = DataLoader(dataset=test_dataset, batch_size=64)# 创建网络模型
tudui = Tudui()
# 创建损失函数
loss_fn = nn.CrossEntropyLoss()
# 创建优化器
# 1e-3 = 1 * 10^(-3) = 0.001
learn_rate = 1e-3
optimizer = torch.optim.SGD(tudui.parameters(), lr=learn_rate)# 设置训练网络的一些参数
# 训练的次数
total_train_step = 0
# 测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10for i in range(epoch):print(f'----第{i+1}轮训练开始----')for data in train_loader:inputs, targets = dataoutputs = tudui(inputs)loss = loss_fn(outputs, targets)# 调用优化器的梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()total_train_step += 1print(f'训练次数: {total_train_step}, Loss: {loss.item()}')
  • loss跟loss.item()的区别在于:
    • 如果loss为tensor格式,那么输出会带有tensor(),而如果我们使用 .item()格式,则不会带有tensor(),如下:
import torcha = torch.tensor(5)
print(a)
print(a.item())# 输出结果:
# tensor(5)
# 5

步骤三:测试模型性能

  • 由于我们每轮训练结束,都需要看模型有没有训练好,所以我们需要用测试集对模型进行测试
  • 同时我们不希望模型根据测试集来更新梯度,即保证测试集不被污染,使用 with torch.no_grad()来关闭梯度计算,
  • 注意:因为此处我们没有使用梯度,所以虽然看起来不写 with torch.no_grad()和写没有什么区别,但是如果不写,就算不把梯度写入模型中,系统仍会计算梯度。而我们在测试时不需要更新参数,即不需要梯度计算,所以在测试过程中它会降低计算效率。
  • 综上:推荐在测试时,关闭梯度计算,代码如下:
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import transformsfrom learn_pytorch.module import Tuduitrain_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=False, transform=transforms.ToTensor(), download=True)# 获得训练数据集和测试数据集的大小
train_dataset_size = len(train_dataset)
test_dataset_size = len(test_dataset)
print('训练数据集大小:', train_dataset_size)
print('测试数据集大小:', test_dataset_size)# 加载训练数据集和测试数据集
train_loader = DataLoader(dataset=train_dataset, batch_size=64)
test_loader = DataLoader(dataset=test_dataset, batch_size=64)# 创建网络模型
tudui = Tudui()
# 创建损失函数
loss_fn = nn.CrossEntropyLoss()
# 创建优化器
# 1e-3 = 1 * 10^(-3) = 0.001
learn_rate = 1e-3
optimizer = torch.optim.SGD(tudui.parameters(), lr=learn_rate)# 设置训练网络的一些参数
# 训练的次数
total_train_step = 0
# 测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10for i in range(epoch):print(f'----第{i+1}轮训练开始----')for data in train_loader:inputs, targets = dataoutputs = tudui(inputs)loss = loss_fn(outputs, targets)# 调用优化器的梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()total_train_step += 1if total_train_step % 100 == 0:print(f'训练次数: {total_train_step}, Loss: {loss.item()}')# 测试模型total_test_loss = 0# 模型运行以下代码时,不会计算梯度,也就是不会更新参数with torch.no_grad():for data in test_loader:inputs, targets = dataoutputs = tudui(inputs)loss = loss_fn(outputs, targets)total_test_loss += loss.item()print(f'测试Loss = {total_test_loss}')

步骤四:在tensorboard中展示输出结果

  • 注意:要在代码的结尾关闭writer
  • 代码如下:
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision.transforms import transformsfrom learn_pytorch.module import Tuduitrain_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=False, transform=transforms.ToTensor(), download=True)# 获得训练数据集和测试数据集的大小
train_dataset_size = len(train_dataset)
test_dataset_size = len(test_dataset)
print('训练数据集大小:', train_dataset_size)
print('测试数据集大小:', test_dataset_size)# 加载训练数据集和测试数据集
train_loader = DataLoader(dataset=train_dataset, batch_size=64)
test_loader = DataLoader(dataset=test_dataset, batch_size=64)# 创建网络模型
tudui = Tudui()
# 创建损失函数
loss_fn = nn.CrossEntropyLoss()
# 创建优化器
# 1e-3 = 1 * 10^(-3) = 0.001
learn_rate = 1e-3
optimizer = torch.optim.SGD(tudui.parameters(), lr=learn_rate)
# 创建tensorboard的writer
writer = SummaryWriter('logs_module')# 设置训练网络的一些参数
# 训练的次数
total_train_step = 0
# 测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10for i in range(epoch):print(f'----第{i+1}轮训练开始----')for data in train_loader:inputs, targets = dataoutputs = tudui(inputs)loss = loss_fn(outputs, targets)# 调用优化器的梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()total_train_step += 1if total_train_step % 100 == 0:print(f'训练次数: {total_train_step}, Loss: {loss.item()}')# 将训练的Loss写入tensorboardwriter.add_scalar('train_loss', loss.item(), total_train_step)# 测试模型total_test_loss = 0# 模型运行以下代码时,不会计算梯度,也就是不会更新参数with torch.no_grad():for data in test_loader:inputs, targets = dataoutputs = tudui(inputs)loss = loss_fn(outputs, targets)total_test_loss += loss.item()# 每轮测试结束后,给测试的次数加1total_test_step += 1print(f'测试Loss = {total_test_loss}')# 将测试的Loss写入tensorboardwriter.add_scalar('test_loss', total_test_loss, total_test_step)writer.close()
  • 结果如下:
    在这里插入图片描述

步骤五:保存每轮模型训练的结果

  • 在每轮测试的代码后,加入以下代码即可:
    torch.save(tudui, f'pth/module{i}')print('模型已保存')

步骤六:计算每轮训练的AP

  • 注意:通过argmax()来得出output的每组序列中哪一个下标的概率最大,()内填1表示横向看,0表示纵向看
  • 注意:通过Preds == target来得出每个预测是否与真实值相同,返回False、True的序列
  • 注意:通过.sum()来计算一共有多少个True
    在这里插入图片描述
  • 代码如下:
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision.transforms import transformsfrom learn_pytorch.module import Tuduitrain_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = torchvision.datasets.CIFAR10(root='Dataset', train=False, transform=transforms.ToTensor(), download=True)# 获得训练数据集和测试数据集的大小
train_dataset_size = len(train_dataset)
test_dataset_size = len(test_dataset)
print('训练数据集大小:', train_dataset_size)
print('测试数据集大小:', test_dataset_size)# 加载训练数据集和测试数据集
train_loader = DataLoader(dataset=train_dataset, batch_size=64)
test_loader = DataLoader(dataset=test_dataset, batch_size=64)# 创建网络模型
tudui = Tudui()
# 创建损失函数
loss_fn = nn.CrossEntropyLoss()
# 创建优化器
# 1e-3 = 1 * 10^(-3) = 0.001
learn_rate = 1e-3
optimizer = torch.optim.SGD(tudui.parameters(), lr=learn_rate)
# 创建tensorboard的writer
writer = SummaryWriter('logs_module')# 设置训练网络的一些参数
# 训练的次数
total_train_step = 0
# 测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10for i in range(epoch):print(f'----第{i+1}轮训练开始----')for data in train_loader:inputs, targets = dataoutputs = tudui(inputs)loss = loss_fn(outputs, targets)# 调用优化器的梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()total_train_step += 1if total_train_step % 100 == 0:print(f'训练次数: {total_train_step}, Loss: {loss.item()}')# 将训练的Loss写入tensorboardwriter.add_scalar('train_loss', loss.item(), total_train_step)# 测试模型total_test_loss = 0total_accuracy = 0# 模型运行以下代码时,不会计算梯度,也就是不会更新参数with torch.no_grad():for data in test_loader:inputs, targets = dataoutputs = tudui(inputs)loss = loss_fn(outputs, targets)total_test_loss += loss.item()accuray = (outputs.argmax(1) == targets).sum()total_accuracy += accurayprint(f'测试准确率 = {total_accuracy / test_dataset_size}')# 每轮测试结束后,给测试的次数加1total_test_step += 1print(f'测试Loss = {total_test_loss}')# 将测试的Loss写入tensorboardwriter.add_scalar('test_loss', total_test_loss, total_test_step)# 将测试的准确率写入tensorboardwriter.add_scalar('test_accuracy', total_accuracy / test_dataset_size, total_test_step)torch.save(tudui, f'pth/module{i}')print('模型已保存')
writer.close()
  • 结果如下:
    在这里插入图片描述

注意事项

  • 在模型的训练代码前,可以加上如下代码,因为有些网络层需要它才能表示训练状态开启:
  • 官网解释如下:
    在这里插入图片描述
# 开始训练
tudui.train()
  • 在模型的测试代码前,也可以加上如下代码,因为有些网络层需要它才能表示测试状态开启:
  • 官网解释如下:
    在这里插入图片描述
tudui.eval()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/537130.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全】 MSF生成木马教程

本文章仅用于信息安全学习,请遵守相关法律法规,严禁用于非法途径。若读者因此作出任何危害网络安全的行为,后果自负,与作者无关。 环境准备: 名称系统IP攻击机Kali Linux10.3.0.231客户端Windows 710.3.0.234 一、生…

设计模式-行为型模式-模版方法模式

模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。[DP] 模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。 //首…

在Linux/Ubuntu/Debian中使用windows应用程序/软件

Wine 是一个兼容层,允许你在类 Unix 操作系统(包括 Ubuntu)上运行 Windows 应用程序。 以下是在 Ubuntu 上安装和使用 Wine 的基本步骤: 在 Ubuntu 上安装 Wine: 更新软件包列表: 打开终端并运行以下命令以…

搭建项目后台系统基础架构

任务描述 1、了解搭建民航后端框架 2、使用IDEA创建基于SpringBoot、MyBatis、MySQL、Redis的Java项目 3、以原项目为参照搭建项目所涉及到的各个业务和底层服务 4、以原项目为例,具体介绍各个目录情况并参照创建相关文件夹 1、创建项目后端 BigData-KongGuan …

实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)

导 读 本文主要介绍使用YOLOv9和OpenCV实现车辆跟踪计数(步骤 源码)。 实现步骤 监控摄像头可以有效地用于各种场景下的车辆计数和交通流量统计。先进的计算机视觉技术(例如对象检测和跟踪)可应用于监控录像,…

软考高级:需求变更管理过程概念和例题

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

IMX8MM -- Yocto构建遇见的错误及解决方法:

IMX8MM Yocto构建遇见的错误及解决方法: 1 bison-3.0.4 error2 Opencv BB_NO_NETWORK Error :3 Yocto构建时出现U-boot 问题4 Yocto构建时出现Linux kernel编译问题5 wayland-native6 cross-localedef-native7 wayland-protocols8 mesa 硬件:…

JAVA初阶数据结构栈(工程文件后续会上传)(+专栏数据结构练习是完整版)

1.栈的概念讲解(Stack)) 定义:栈是一种先进后出的数据结构 要想拿到12就要把它头上的所有东西给移出去 2.栈的实现(代码) 2.1栈的方法逻辑的讲解 (1)新建一个测试类Frank (2)进…

借助ChatGPT提高编程效率指南

PS: ChatGPT无限次数,无需魔法,登录即可使用,网页打开下面 一、借助ChatGPT提高编程效率指南 随着计算机技术的飞速发展,编程已经成为了现代社会中一个非常重要的技能。对于许多人来说,编程不仅是一项工作技能,而且是…

【linux】搜索所有目录和子目录下的包含.git的文件并删除

一、linux命令搜索所有目录和子目录下的包含.git的文件 在Linux系统中,要搜索所有目录和子目录下的包含.git的文件,可以使用find命令。find命令允许指定路径、表达式和操作来查找文件。 以下是使用find命令搜索包含.git的文件的方法: 1. 基…

《高效便捷,探索快递柜系统架构的智慧之路》

随着电商业务的蓬勃发展,快递柜系统作为一种高效、便捷的最后一公里配送解决方案,正在受到越来越多企业和消费者的青睐。本篇博客将深入探讨快递柜系统的架构设计理念、优势和实践,帮助读者了解如何构建智能化的快递柜系统,提升物…

STM32平替GD32有多方便

众所周知, GD32一直模仿STM32,从未被超越。 我最近公司使用的GD32E230C6T6 这款芯片有48个引脚。 属于小容量的芯片。 我有一个用STM32写的代码,之前是用的 STM32F103CB 这款芯片是中容量的。 不过在keil中,只需要这两步,就能使用原来的逻辑,几乎不用修改代码。 1. …