当前位置: 首页 > news >正文

第七章 Pytorch构建模型详解【构建CIFAR10模型结构】

跟着小土堆继续学,在上篇的学习中已经掌握了对Pytorch的基本使用 ,这篇构建模型练手

前置知识

 container中Sequential的使用:

作用:将按各个模块按顺序搭建起来

CIFAR10网络模型结构

卷积输入输出计算公式

通过卷积的输出公式计算就可以根据输入和输出的图像形状反推出padding等值

模型

模型搭建

class CIFAR10_Net(nn.Module):def __init__(self):super(CIFAR10_Net, self).__init__()self.model = nn.Sequential(      #Sequential将按各个模块按顺序搭建起来#卷积输入输出计算:32 = (32 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 32,stride = 1,dilation = 1,kernel_size = 5,Hout = 32】nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),      #第一步是5*5的卷积【将(3*32*32)的图片转为(32*32*32)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第二步是2*2最大池化【将(32*32*32)的数据转为(32*16*16)的数据】#卷积输入输出计算:16 = (16 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 16,stride = 1,dilation = 1,kernel_size = 5,Hout = 16】nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),     #第三步还是5*5的卷积【将(32*16*16)的数据转为(32*16*16)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第四步还是2*2最大池化【将(32*16*16)的数据转为(32*8*8)的数据】# 卷积输入输出计算:8 = (8 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 8,stride = 1,dilation = 1,kernel_size = 5,Hout = 8】nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2),     #第五步还是5*5的卷积【将(32*8*8)的数据转为(64*8*8)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第六步还是2*2最大池化【将(64*8*8)的数据转为(64*4*4)的数据】nn.Flatten(),                                                                       #第七步展平数据【将(64*4*4)的数据转为64*4*4的数据】#全连接层#上面经过model已经得到数据,接下来要将数据转为输出结构nn.Linear(64*4*4,64),                                                    #第八步线性连接进入隐藏层【将64*4*4的数据输入计算出64个隐藏层结果】nn.Linear(64,10)                                               #第九步线性连接得出预测【将64的数据输入计算出10个预测结果的分数】)def forward(self, x):x = self.model(x)x = self.fc1(x)x = self.fc2(x)return x

测试验证模型

#模型实例化
cifar10_net = CIFAR10_Net()                                                                 
print(cifar10_net)#测试数据【ones代表全为1,random即随机】
input = torch.ones(64, 3, 32, 32)                                                           
output = cifar10_net(input)print(output.shape)

Tensorboard展示

writer = SummaryWriter("./logs_model")
writer.add_graph(cifar10_net, input)
writer.close()

Loss损失函数

求和平均L1Loss

#L1Loss
inputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)inputs = torch.reshape(inputs, (1,1,1,3))
targets = torch.reshape(targets, (1,1,1,3))loss = L1Loss()            #默认为mean——求和平均,如果是reduction="sum"就是统计总数result = loss(inputs, targets)
print(result)

平方差MSELoss

#MSELoss
inputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)inputs = torch.reshape(inputs, (1,1,1,3))
targets = torch.reshape(targets, (1,1,1,3))loss = MSELoss()                #默认为mean——求和平均,如果是reduction="sum"就是统计总数result = loss(inputs, targets)
print(result)

交叉熵CrossEntropyLoss

CrossEntropyLoss输入要求

#CrossEntropyLoss
inputs = torch.tensor([0.1,0.2,0.3],dtype=torch.float32)
targets = torch.tensor([1])         #标签inputs = torch.reshape(inputs, (1,3))   #CrossEntropyLoss要求的输入形状是(N,C) =》(batch_size,number of class)loss = CrossEntropyLoss()result = loss(inputs, targets)
print(result)

损失的梯度计算

梯度计算即是反向传播,通过利用backward函数进行计算,计算好的结果会存放到model中

给result_loss.backward()这一步打上断点,执行调试【右上角的虫子,在运行旁边】

执行result_loss.backward()这一步后,梯度结果就会存放在model中【我们输入的output数据类型是tensor,而tensor中会保存计算的前向路径,因此backward就可以自动追踪路径定位到相应model,往其中存放梯度grad】

优化器optimizer

通过损失函数我们已经计算出了模型中各参数的梯度grad,优化器optimizer的作用就是根据梯度进行参数更新

使用示例

【optimizer.step()的作用就是根据梯度gard更新参数,而optimizer.zero_grad()是清空model中的梯度,以防止上次的梯度影响这次优化器优化,接着重新利用loss.back()重新计算梯度,循环往复】

【1】梯度清零

【2】反向传播求梯度

【3】根据梯度,优化器更新参数

更新前

更新后

【4】循环往复(重复前面的步骤)

以上遍历完整个数据集(训练集)就相当于一轮学习,我们训练时往往要经过多轮学习,不断优化model参数

for epoch in range(20):running_loss = 0.0                                                                      #统计这一轮的总损失for i, (images, labels) in enumerate(train_loader):                                     #训练optimizer.zero_grad()                                                               #梯度清空【清空上一轮计算出的梯度(将model中的grad都设为None)】outputs = cifar10_net(images)                                                       #模型输出结果【预测标签】result_loss = loss(outputs, labels)                                                 #损失函数计算result_loss.backward()                                                              #根据反向传播计算出model中各参数的梯度gradoptimizer.step()                                                                    #优化器optimizer根据梯度更新model中的各参数running_loss += result_loss                                                         #统计这一轮的总损失print('epoch:{}, running_loss:{}'.format(epoch, running_loss))                    #输出这一轮的总损失

网络模型读取和保存

模型保存

保存方式1:save(model,save_path)【完全保存】

 保存网络模型的同时也保存相应的参数,“.pth”的后缀其实取什么都可以,但是默认是.pth

【注意:该方式加载预训练模型时要求文件中含有model的类(import导入或直接定义,一边都是import导入)】

#保存方式1
#保存模型
torch.save(cifar10_net, "cifar10_net.pth")          #保存网络模型的同时也保存相应的参数,“.pth”的后缀其实取什么都可以,但是默认是.pth#加载模型
load_net = torch.load("cifar10_net.pth")
print(load_net)

保存方式2:save(model.state_dict,save_path)【只保存参数字典】

只保存模型相应的参数,不保存模型的网络结构(官方推荐,保存下来占用的空间小)

#保存方式2(官方推荐,保存下来占用的空间小)
#保存模型
torch.save(cifar10_net.state_dict(), "cifar10_dict.pth")          #用字典保存模型相应的参数,不保存模型的网络结构#加载模型
load_net = CIFAR10_Net()                        #实例化模型
load_dict = torch.load("cifar10_dict.pth")      #加载参数字典
load_net.load_state_dict(load_dict)             #将参数字典加载到模型结构汇总
print(load_net)

现有网络模型(Pytorch提供)的使用

VGG的使用

VGG对应的数据集ImageNet

数据集下载(需在虚拟环境中提前安装scipy包)

Train_Dataset = torchvision.datasets.ImageNet(root='./ImageNet_data',split='train',transform=torchvision.transforms.ToTensor())Test_Dataset = torchvision.datasets.ImageNet(root='./ImageNet_data',split='val',transform=torchvision.transforms.ToTensor())train_loader = torch.utils.data.DataLoader(dataset=Train_Dataset,batch_size=64)
test_loader = torch.utils.data.DataLoader(dataset=Test_Dataset,batch_size=64)

上网下载【不做验证了,数据集太大了,百来个G】

加载预训练模型

VGG16_false = torchvision.models.vgg16(pretrained=False,            #仅加载网络模型(随机初始化权重)progress=True)VGG16_true = torchvision.models.vgg16(pretrained=True,              #加载网络模型并且初试参数设置为预定的权重(别人已经训练好了的参数)progress=True)

修改现有网络模型结构

方式1:修改原模型

#方式1:修改原模型
VGG16_false.classifier[6] = nn.Linear(4096, 10)print(VGG16_false)

方式2:追加线性层

使用add_module()函数

#追加线性层
VGG16_false.add_module("add_linear",nn.Linear(1000,10))print(VGG16_false)

加到classifier(Sequential构造的一连串模块)中

VGG16_false.classifier.add_module("add_linear",nn.Linear(1000,10))print(VGG16_false)

模型训练套路

建立model.py存放模型结构

import torch
from torch import nn#======================================================================模型搭建======================================================================class CIFAR10_Net(nn.Module):def __init__(self):super(CIFAR10_Net, self).__init__()self.model = nn.Sequential(      #Sequential将按各个模块按顺序搭建起来#卷积输入输出计算:32 = (32 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 32,stride = 1,dilation = 1,kernel_size = 5,Hout = 32】nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),      #第一步是5*5的卷积【将(3*32*32)的图片转为(32*32*32)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第二步是2*2最大池化【将(32*32*32)的数据转为(32*16*16)的数据】#卷积输入输出计算:16 = (16 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 16,stride = 1,dilation = 1,kernel_size = 5,Hout = 16】nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),     #第三步还是5*5的卷积【将(32*16*16)的数据转为(32*16*16)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第四步还是2*2最大池化【将(32*16*16)的数据转为(32*8*8)的数据】# 卷积输入输出计算:8 = (8 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 8,stride = 1,dilation = 1,kernel_size = 5,Hout = 8】nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2),     #第五步还是5*5的卷积【将(32*8*8)的数据转为(64*8*8)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第六步还是2*2最大池化【将(64*8*8)的数据转为(64*4*4)的数据】nn.Flatten(),                                                                       #第七步展平数据【将(64*4*4)的数据转为64*4*4的数据】#全连接层#上面经过model已经得到数据,接下来要将数据转为输出结构nn.Linear(64*4*4,64),                                                    #第八步线性连接进入隐藏层【将64*4*4的数据输入计算出64个隐藏层结果】nn.Linear(64,10)                                               #第九步线性连接得出预测【将64的数据输入计算出10个预测结果的分数】)def forward(self, x):x = self.model(x)return x#======================================================================测试验证模型======================================================================if __name__ == '__main__':                                                                      #main函数==》只在执行本文件时运行,当作为类使用时,这部分不会被引入【目的在于测试该文件,有更好的规范性】cifar10_net = CIFAR10_Net()                                                                 #模型实例化print(cifar10_net)input = torch.ones(64, 3, 32, 32)                                                           #测试数据【ones代表全为1,random即随机】output = cifar10_net(input)print(output.shape)

cuda(GPU)加速模型训练

环境配置

检查cuda能否使用

print('Pytorch版本:', torch.__version__)
print('显卡是否可用:', '可用' if (torch.cuda.is_available()) else '不可用')

以下是有英伟达显卡但是cuda不能使用的情况:

【情况一:Pytorch版本不对(没下载到cuda版本的Pytorch)】

解决:重新安装Pytorch

(1)进入虚拟环境中卸载cpu版本的Pytorch

activate tudui
conda uninstall pytorch

(2)去Pytorch官方下载对应cuda版本的Pytorch

查看自己的cuda版本:

win+r输入cmd回车进入命令行,输入:

nvidia-smi

在Pytorch官网中找到对应版本的下载链接Get Started

下载

【情况二:Pytorch版本与cuda版本不匹配(某些项目可能会出现版本不匹配的问题)】

在确认自己的cuda版本后,在Pytorch官方找到对应版本的Pytorch下载链接,重复上面的操作

以前的 PyTorch 版本

以上成功解决后,我们就可以用cuda把我们训练放到GPU上,加速训练

使用to(device)函数加载

#定义训练设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")                 #cuda:0代表第一个GPU(如果你有多个GPU的话),如果没有GPU就用CPU
cifar10_net.to(device)                                                                  #将模型加载到GPU上

训练train函数设计

导入模型以及各种包

from typing import OrderedDict
import torch
import torchvision
from torch import nn
from torch.nn import L1Loss, MSELoss, CrossEntropyLoss
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms#引入model
from model import *

数据加载

#======================================================================数据加载======================================================================train_dataset = torchvision.datasets.CIFAR10(root='./dataset',                              #训练集train=True,download=True,transform=transforms.ToTensor())test_dataset = torchvision.datasets.CIFAR10(root='./dataset',                               #测试集train=False,download=True,transform=transforms.ToTensor())#查询数据集长度
train_len = len(train_dataset)
test_len = len(test_dataset)print('Train dataset length:', train_len)
print('Test dataset length:', test_len)train_loader = torch.utils.data.DataLoader(train_dataset,64)                                #数据加载
test_loader = torch.utils.data.DataLoader(test_dataset, 64)

实例化模型

#======================================================================创建模型实例对象======================================================================#确认cuda可用
print('CUDA版本:', torch.version.cuda)
print('Pytorch版本:', torch.__version__)
print('显卡是否可用:', '可用' if (torch.cuda.is_available()) else '不可用')cifar10_net = CIFAR10_Net()                                                           #模型实例化
cifar10_net = cifar10_net.cuda()                                                      #放到cuda(GPU)上加载

实例化损失函数

#======================================================================Loss损失函数======================================================================loss = CrossEntropyLoss()                                                               #设置交叉熵损失
loss = loss.cuda()                                                                      #放到cuda(GPU)上加载

实例化优化器

#======================================================================优化器optimizer======================================================================optimizer = torch.optim.SGD(cifar10_net.parameters(), lr=1e-2, momentum=0.9)            #优化器设置(SGD是随机梯度下降,1e-2即是1*(10)**2 = 0.01)

模型训练以及测试与保存

模型测试中模型效果衡量标准为acc(分类任务中常用指标),即对比模型输出结果和标签查看是否一致,一致则说明我们的预测正确,对比完整个测试集后,acc = 预测正确数/测试总数

得到output后,我们使用argmax(dim = 1)进行分析结果,其中对output来说就相当于一个二维数组(在本案例中),而dim的作用是指定相应的维度,dim = 1即是第二维(第一维是dim = 0),拿其中一个输出i举例:

dim = 1相对应的就是第i个输出output[i][]的一行(设第一维为列,第二维为行),argmax的作用就是选出其中最大元素所在的下标(代表最大概率的分类),如果一个output为[0.1,0.2,0.4,0.3] —> argmax返回的就是下标3,此时查看target的标记是多少,如果target为3,即两者相等,预测正确,反之错误

#======================================================================训练过程======================================================================#记录训练的步数
train_step = 0
#记录测试的步数
test_step = 0
#训练轮数
epochs = 10
#加载到Tensorboard中
writer = SummaryWriter("./logs_model_loss")for epoch in range(epochs):for i, (images, labels) in enumerate(train_loader):                                     #训练images = images.to('cuda')                                                          #放到cuda(GPU)上加载labels = labels.to('cuda')                                                          #放到cuda(GPU)上加载optimizer.zero_grad()                                                               #梯度清空【清空上一轮计算出的梯度(将model中的grad都设为None)】outputs = cifar10_net(images)                                                       #模型输出结果【预测标签】result_loss = loss(outputs, labels)                                                 #损失函数计算result_loss.backward()                                                              #根据反向传播计算出model中各参数的梯度gradoptimizer.step()                                                                    #优化器optimizer根据梯度更新model中的各参数                                                       #统计这一轮的总损失train_step += 1if train_step % 100 == 0:                                                           #每训练一百次打印一次结果print("Train_Step [{}/{}], Loss: {:.4f}".format(train_step, train_len,result_loss))writer.add_scalar('Loss/train', result_loss.item(), train_step)             #将损失使用坐标轴显示出来#======================================================================测试过程======================================================================#每一轮epoch训练完后都经过测试with torch.no_grad():                                                                   #with torch.no_grad()———以下部分的梯度全部清空,保证模型不会因为梯度影响测试结果test_loss = 0                                                                       #测试的总损失test_accuracy = 0                                                                   #衡量指标:预测准确度accfor i, (images, labels) in enumerate(test_loader):images = images.to('cuda')                                                      #放到cuda(GPU)上加载labels = labels.to('cuda')                                                      #放到cuda(GPU)上加载outputs = cifar10_net(images)                                                   #模型的测试输出result_loss = loss(outputs, labels)                                             #测试误差test_loss += result_loss                                                        #测试总误差统计test_step += 1test_accuracy += (outputs.argmax(dim=1) == labels).sum()                                #统计预测正确的个数writer.add_scalar('Loss/test', test_loss.item(), test_step)  # 将损失使用坐标轴显示出来writer.add_scalar('Accuracy/test', test_accuracy/test_len, test_step)print('===========================epoch:{},acc = {},Test_loss = {}=============================='.format(epoch+1, test_accuracy/test_len, epochs,test_loss))#======================================================================模型保存======================================================================#每一轮epoch结束,保存一次模型# 保存方式2(官方推荐,保存下来占用的空间小)torch.save(cifar10_net.state_dict(), "cifar10_dict_epcoh{}.pth".format(epoch))  # 用字典保存模型相应的参数,不保存模型的网络结构print("model saved")
writer.close()

将我们的输出结果放到Tensorboard中

测试test函数设计

数据加载

#======================================================================数据加载======================================================================test_dataset = torchvision.datasets.CIFAR10(root='./dataset',                               #测试集train=False,download=True,transform=transforms.ToTensor())#查询数据集长度
test_len = len(test_dataset)
print('Test dataset length:', test_len)test_loader = torch.utils.data.DataLoader(test_dataset, 64)                        #数据加载

实例化模型并加载预训练参数

#======================================================================创建模型实例对象======================================================================#确认cuda可用
print('CUDA版本:', torch.version.cuda)
print('Pytorch版本:', torch.__version__)
print('显卡是否可用:', '可用' if (torch.cuda.is_available()) else '不可用')cifar10_net = CIFAR10_Net()                                                           #模型实例化
cifar10_net = cifar10_net.cuda()                                                      #放到cuda(GPU)上加载#加载模型
load_dict = torch.load("cifar10_dict_epcoh9.pth")                                            #加载参数字典
cifar10_net.load_state_dict(load_dict)                                                #将参数字典加载到模型结构汇总
print(cifar10_net)                                                                    #打印网络结构

实例化损失函数

#======================================================================Loss损失函数======================================================================loss = CrossEntropyLoss()                                                               #设置交叉熵损失

测试过程

#======================================================================测试过程======================================================================test_loss = 0                                                                       #测试的总损失
test_accuracy = 0                                                                   #衡量指标:预测准确度acc
for i, (images, labels) in enumerate(test_loader):images = images.to('cuda')                                                      #放到cuda(GPU)上加载labels = labels.to('cuda')                                                      #放到cuda(GPU)上加载outputs = cifar10_net(images)                                                   #模型的测试输出result_loss = loss(outputs, labels)                                             #测试误差test_loss += result_loss                                                        #测试总误差统计test_accuracy += (outputs.argmax(dim=1) == labels).sum()                        #统计预测正确的个数print('===========================acc = {},Test_loss = {}=============================='.format(test_accuracy/test_len, test_loss))

补充

下面两个函数其实要不要都不影响训练,但是针对特定层的处理往往要用到

train()函数

eval()函数

具体影响的层

Dropout 层
  • 训练时:随机丢弃部分神经元(如 50%),防止过拟合。
  • 评估时:关闭丢弃机制,保留所有神经元进行计算。
Batch Normalization (BN)
  • 训练时:使用当前批次数据的均值和方差进行归一化,并更新全局统计量(running_mean/running_var)。
  • 评估时:使用训练阶段积累的全局统计量,而非当前批次数据,确保结果稳定。

代码文件

model.py

import torch
from torch import nn#======================================================================模型搭建======================================================================class CIFAR10_Net(nn.Module):def __init__(self):super(CIFAR10_Net, self).__init__()self.model = nn.Sequential(      #Sequential将按各个模块按顺序搭建起来#卷积输入输出计算:32 = (32 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 32,stride = 1,dilation = 1,kernel_size = 5,Hout = 32】nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),      #第一步是5*5的卷积【将(3*32*32)的图片转为(32*32*32)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第二步是2*2最大池化【将(32*32*32)的数据转为(32*16*16)的数据】#卷积输入输出计算:16 = (16 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 16,stride = 1,dilation = 1,kernel_size = 5,Hout = 16】nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),     #第三步还是5*5的卷积【将(32*16*16)的数据转为(32*16*16)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第四步还是2*2最大池化【将(32*16*16)的数据转为(32*8*8)的数据】# 卷积输入输出计算:8 = (8 + 2 * padding - 1 * (5-1) - 1) + 1得到padding为2【Hin = 8,stride = 1,dilation = 1,kernel_size = 5,Hout = 8】nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2),     #第五步还是5*5的卷积【将(32*8*8)的数据转为(64*8*8)的数据】nn.MaxPool2d(kernel_size=2, stride=2),                                              #第六步还是2*2最大池化【将(64*8*8)的数据转为(64*4*4)的数据】nn.Flatten(),                                                                       #第七步展平数据【将(64*4*4)的数据转为64*4*4的数据】#全连接层#上面经过model已经得到数据,接下来要将数据转为输出结构nn.Linear(64*4*4,64),                                                    #第八步线性连接进入隐藏层【将64*4*4的数据输入计算出64个隐藏层结果】nn.Linear(64,10)                                               #第九步线性连接得出预测【将64的数据输入计算出10个预测结果的分数】)def forward(self, x):x = self.model(x)return x#======================================================================测试验证模型======================================================================if __name__ == '__main__':                                                                      #main函数==》只在执行本文件时运行,当作为类使用时,这部分不会被引入【目的在于测试该文件,有更好的规范性】cifar10_net = CIFAR10_Net()                                                                 #模型实例化print(cifar10_net)input = torch.ones(64, 3, 32, 32)                                                           #测试数据【ones代表全为1,random即随机】output = cifar10_net(input)print(output.shape)

train_model.py

from typing import OrderedDict
import torch
import torchvision
from torch import nn
from torch.nn import L1Loss, MSELoss, CrossEntropyLoss
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms#引入model
from model import *#======================================================================数据加载======================================================================train_dataset = torchvision.datasets.CIFAR10(root='./dataset',                              #训练集train=True,download=True,transform=transforms.ToTensor())test_dataset = torchvision.datasets.CIFAR10(root='./dataset',                               #测试集train=False,download=True,transform=transforms.ToTensor())#查询数据集长度
train_len = len(train_dataset)
test_len = len(test_dataset)print('Train dataset length:', train_len)
print('Test dataset length:', test_len)train_loader = torch.utils.data.DataLoader(train_dataset,64)                                #数据加载
test_loader = torch.utils.data.DataLoader(test_dataset, 64)#======================================================================创建模型实例对象======================================================================#确认cuda可用
print('CUDA版本:', torch.version.cuda)
print('Pytorch版本:', torch.__version__)
print('显卡是否可用:', '可用' if (torch.cuda.is_available()) else '不可用')cifar10_net = CIFAR10_Net()                                                           #模型实例化
cifar10_net = cifar10_net.cuda()                                                      #放到cuda(GPU)上加载#======================================================================Loss损失函数======================================================================loss = CrossEntropyLoss()                                                               #设置交叉熵损失#======================================================================优化器optimizer======================================================================optimizer = torch.optim.SGD(cifar10_net.parameters(), lr=1e-2, momentum=0.9)            #优化器设置(SGD是随机梯度下降,1e-2即是1*(10)**2 = 0.01)#======================================================================训练过程======================================================================#记录训练的步数
train_step = 0
#记录测试的步数
test_step = 0
#训练轮数
epochs = 10
#加载到Tensorboard中
writer = SummaryWriter("./logs_model_loss")for epoch in range(epochs):for i, (images, labels) in enumerate(train_loader):                                     #训练images = images.to('cuda')                                                          #放到cuda(GPU)上加载labels = labels.to('cuda')                                                          #放到cuda(GPU)上加载optimizer.zero_grad()                                                               #梯度清空【清空上一轮计算出的梯度(将model中的grad都设为None)】outputs = cifar10_net(images)                                                       #模型输出结果【预测标签】result_loss = loss(outputs, labels)                                                 #损失函数计算result_loss.backward()                                                              #根据反向传播计算出model中各参数的梯度gradoptimizer.step()                                                                    #优化器optimizer根据梯度更新model中的各参数                                                       #统计这一轮的总损失train_step += 1if train_step % 100 == 0:                                                           #每训练一百次打印一次结果print("Train_Step [{}/{}], Loss: {:.4f}".format(train_step, train_len,result_loss))writer.add_scalar('Loss/train', result_loss.item(), train_step)             #将损失使用坐标轴显示出来#======================================================================测试过程======================================================================#每一轮epoch训练完后都经过测试with torch.no_grad():                                                                   #with torch.no_grad()———以下部分的梯度全部清空,保证模型不会因为梯度影响测试结果test_loss = 0                                                                       #测试的总损失test_accuracy = 0                                                                   #衡量指标:预测准确度accfor i, (images, labels) in enumerate(test_loader):images = images.to('cuda')                                                      #放到cuda(GPU)上加载labels = labels.to('cuda')                                                      #放到cuda(GPU)上加载outputs = cifar10_net(images)                                                   #模型的测试输出result_loss = loss(outputs, labels)                                             #测试误差test_loss += result_loss                                                        #测试总误差统计test_step += 1test_accuracy += (outputs.argmax(dim=1) == labels).sum()                                #统计预测正确的个数writer.add_scalar('Loss/test', test_loss.item(), test_step)  # 将损失使用坐标轴显示出来writer.add_scalar('Accuracy/test', test_accuracy/test_len, test_step)print('===========================epoch:{},acc = {},Test_loss = {}=============================='.format(epoch+1, test_accuracy/test_len, epochs,test_loss))#======================================================================模型保存======================================================================#每一轮epoch结束,保存一次模型# 保存方式2(官方推荐,保存下来占用的空间小)torch.save(cifar10_net.state_dict(), "cifar10_dict_epcoh{}.pth".format(epoch))  #用字典保存模型相应的参数,不保存模型的网络结构print("model saved")
writer.close()

test_model.py

from typing import OrderedDict
import torch
import torchvision
from torch import nn
from torch.nn import L1Loss, MSELoss, CrossEntropyLoss
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms#引入model
from model import *#======================================================================数据加载======================================================================test_dataset = torchvision.datasets.CIFAR10(root='./dataset',                               #测试集train=False,download=True,transform=transforms.ToTensor())#查询数据集长度
test_len = len(test_dataset)
print('Test dataset length:', test_len)test_loader = torch.utils.data.DataLoader(test_dataset, 64)                        #数据加载#======================================================================创建模型实例对象======================================================================#确认cuda可用
print('CUDA版本:', torch.version.cuda)
print('Pytorch版本:', torch.__version__)
print('显卡是否可用:', '可用' if (torch.cuda.is_available()) else '不可用')cifar10_net = CIFAR10_Net()                                                           #模型实例化#加载模型
load_dict = torch.load("cifar10_dict_epcoh9.pth")                                            #加载参数字典
cifar10_net.load_state_dict(load_dict)                                                #将参数字典加载到模型结构汇总
print(cifar10_net)                                                                    #打印网络结构#定义训练设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")                 #cuda:0代表第一个GPU(如果你有多个GPU的话),如果没有GPU就用CPU
cifar10_net.to(device)                                                                  #将模型加载到GPU上#======================================================================Loss损失函数======================================================================loss = CrossEntropyLoss()                                                               #设置交叉熵损失
loss.to(device)                                                                     #放到cuda(GPU)上加载#======================================================================测试过程======================================================================test_loss = 0                                                                       #测试的总损失
test_accuracy = 0                                                                   #衡量指标:预测准确度acc
for i, (images, labels) in enumerate(test_loader):images = images.to(device)                                                      #放到cuda(GPU)上加载labels = labels.to(device)                                                      #放到cuda(GPU)上加载outputs = cifar10_net(images)                                                   #模型的测试输出result_loss = loss(outputs, labels)                                             #测试误差test_loss += result_loss                                                        #测试总误差统计test_accuracy += (outputs.argmax(dim=1) == labels).sum()                        #统计预测正确的个数print('===========================acc = {},Test_loss = {}=============================='.format(test_accuracy/test_len, test_loss))
http://www.lryc.cn/news/597525.html

相关文章:

  • 【WRF】根据自动安装脚本安装 WRF / WRF-CHEM等
  • Google Chrome V8< 14.0.221 类型混淆漏洞
  • linux中如何清除history命令
  • IAR Embedded Workbench for ARM 8.1 安装教程
  • 有没有能读懂PDF里手写批注的工具?
  • C# 值类型与引用类型的储存方式_堆栈_
  • 基于Kafka实现简单的延时队列
  • 【JVM】从 JVM 整体说明 JVM 运行的完整流程
  • C#与WPF使用mvvm简单案例点击按钮触发弹窗
  • 基于阿里云平台的文章评价模型训练与应用全流程指南
  • nginx.conf配置文件以及指令详解
  • 人工智慧是引擎,人类是方向盘:Vitalik对AI未来的深刻反思
  • 关于SPring基础和Vue的学习
  • rust嵌入式开发零基础入门教程(六)
  • 什么是MySQL 视图
  • 综合实验(3)
  • 暑期自学嵌入式——Day06(C语言阶段)
  • 7月23日星期三今日早报简报微语报早读
  • 51c大模型~合集158
  • Vue 3 组件通信全解析:从 Props 到 Pinia 的深入实践
  • 用 llama.cpp 构建高性能本地 AI 应用:从环境搭建到多工具智能体开发全流程实战
  • Python应用指南:构建和获取全球地铁线路数据及可视化
  • ToBToC的定义与区别
  • 从 XSS 到 Bot 攻击:常见网络攻击防不胜防?雷池 WAF 用全场景防护为网站筑牢安全墙
  • Java中IO多路复用技术详解
  • S段和G段到底有什么区别
  • 基于springboot的乡村旅游在线服务系统/乡村旅游网站
  • 网络--VLAN技术
  • 在 Ubuntu 20.04.5 LTS 系统上安装 Docker CE 26.1.4 完整指南
  • OpenLayers 快速入门(五)Controls 对象