基于PyTorch框架下网络模型的使用与修改

目录

  • 1 损失函数和反向传播
    • 1.1 损失函数
    • 1.2 反向传播
  • 2 优化器
  • 3 现有网络模型的使用及修改
  • 4 网络模型的保存与读取
    • 4.1 网络模型的保存
    • 4.2 网络模型的读取(加载)
  • 5 完整的模型训练套路
  • 6 利用GPU训练模型
  • 7 完整的模型验证套路:

1 损失函数和反向传播

1.1 损失函数

前言: torch.nn里面的Loss Functions用来衡量误差。
什么是Loss Functions呢?它的作用是什么呢?
答:比如说一张总分为100(也就是target为100)的试卷由选择、填空、解答三部分组成,选择占30分,填空占20分,解答占50分。但是我们实际考了多少分呢?假设选择考了10分,填空考了20分,解答考了50分,则实际的总分为30分(也就是实际输出的output=30)。那么我们就需要用一个Loss来衡量实际我们考的分数(也就是神经网络的输出)和我们真实想要的结果(也就是总分100分)之间的差距,比如说这里的Loss算出来是差距了70分。我们得到这个差距之后,要根据这个差距来指导我们让output去接近target。所以说这个Loss(误差)在大多数情况下按照定义肯定是越小越好。
我们要根据Loss去提高output的输出,比如说我们对神经网络经过不断的训练。训练的依据就从Loss来,比如通过看这个分数,看到我们的解答题实在是太弱了,所以我们要对这个解答题多训练训练,对解答题这个模块着重的进行一下更新。再比如说经过我们的努力解答题进行了一个上升考了20分,那么它这个Loss就会进行一个相应的下降。
所以说Loss Functions的作用主要是:(1)计算实际输出和目标之间的差距;(2)为我们更新输出提供一定的依据(这其实就是反向传播)。
一个实例进行具体理解:
nn_loss.py

import torch
from torch.nn import L1loss
from torch import nninputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)#这里把inputs、targets的格式都变成了1batch_size,1channel,1行3列
inputs = torch.reshape(inputs,(1,1,1,3))
targets = torch.reshape(targets,(1,1,1,3))#然后我们求我们的这个loss
#这里以L1loss函数进行举例使用的
#括号里什么都没写的话,说明我们这里L1loss这个函数所实现的公式是误差相加之后求一个平均值,这个平均值就是最后的返回结果
loss = L1loss()
#如果我们把这里reduction这个参数设置为sum,则意思为误差相加。说明我们这里L1loss这个函数所实现的公式是误差相加,这个相加后的数值就是最后的返回结果
#loss = L1loss(reduction='sum')
#运行以后我们会发现它要求的数据类型要是浮点数,不能是Long,否则就会报错
result = loss(inputs,targets)#这里以MSELoss函数进行举例使用的
#括号里什么都没写的话,说明我们这里MSELoss这个函数所实现的公式就是平方差求和之后再求平均的公式,这个平均值就是最后的返回结果
#平方差求和之后再求平均的公式:[(x1-y1)的平方+(x2-y2)的平方...+(xn-yn)的平方]/n
loss_mse = MSELoss()
result_mse = loss_mse(inputs,targets)print(result)
#运行结果为tensor(0.6667)
#如果我们把这里reduction这个参数设置为sum,运行结果为tensor(2.)
print(result_mse)
#运行结果为tensor(1.3333)#这里以CrossEntropyLoss(交叉熵)函数进行举例使用的
#这个函数一般用在:当你训练一个分类问题的时候,这个分类问题有C个类别,比如像我们CIFAR10这个数据集里面有10个分类类别。
#对于这个函数计算公式的理解如图一所示:比如现在有一个三分类的问题,分成了Person、dog、cat三类,我们现在拿出了一张dog的图片当作输入,经过神经网络之后会产生一个预测出来的概率,比如说Person的概率是0.1,dog的概率是0.2,cat的概率是0.3(即给一个output为[0.1,0.2,0.3])。但是实际过程会给一个target为1(这个1的意思就是dog的意思[Person代表第0位、dog代表第1位、cat代表第2位])
#接着我们计算交叉熵的时候,公式里面的x指的就是[0.1,0.2,0.3],target的那个1指的就是class,代入公式可得Loss(x,class)=-0.2+log(exp(0.1)+exp(0.2)+exp(0.3))。
#如果你想要loss越来越小的话,exp(0.1)+exp(0.2)+exp(0.3)也就要比较小,它就能保证我们预测成Person、dog、cat比较合理。不然预测的三个值为0.8、0.9、0.8这种,三个都比较高的话看不出来差距,这个分类器的能力就不会很强。所以log(exp(0.1)+exp(0.2)+exp(0.3))是来限制概率分布的。
#-x[class]也要比较小,所以x[class]这部分就要求比较大。
x = torch.tensor([0.1,0.2,0.3])
y = torch.tensor([1])
#这里意思是把x变成了1batch_size,3类的格式
x = torch.reshape(x,(1,3))
loss_cross = nn.CrossEntropyLoss()
return_cross = loss_cross(x,y)
print(return_cross)
#运行结果为tensor(1.1019)

图一:在这里插入图片描述
接下来再来看看如何在之前写的神经网络中用到Loss Function(损失函数)呢?
nn_loss_network.py

from torch import nn
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.ensorboard import SummaryWriter#获取数据集
dataset = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
#加载数据到神经网络中去
dataloader = Dataloader(dataset,batch_size=1)class Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.model1 = Sequential(Conv2d(3,32,5,stride=1,padding=2),MaxPool2d(2),Conv2d(32,32,5,stride=1,padding=2),MaxPool2d(2),Conv2d(32,64,5,stride=1,padding=2),MaxPool2d(2),Flatten(),Linear(1024,64),Linear(64,10))def forward(self,x):x = self.model1 (x)return x#这种分类问题可以用前面介绍过的交叉熵进行loss的计算
loss = nn.CrossEntropyLoss()#初始化这个网络
feihan = Feihan()
for data in dataloader:imgs,targets = dataoutputs = feihan(imgs)#我们需要看一下outputs和targets长什么样,看选择什么样的损失函数#print(outputs)#print(targets)#运行结果格式类似于:#tensor([[-0.0731,0.0964,...]])括号里面有10个数字,每个代表预测是这个类别的概率#tensor([3])代表我们真实的targets是3result_loss = loss(outputs,targets)print(result_loss)#运行结果格式类似于:tensor(2.3247),代表神经网络中的输出和我们真实输出之间的一个误差    

1.2 反向传播

那么它是如何为我们更新输出提供一定的依据(这其实就是反向传播)呢?
答:它就是给我们每一个需要调优的参数,对神经网络来说,或者对卷积层来说,其中的每一个卷积核当中的参数就是我们需要进行调的。它对我们每一个卷积核当中的参数设置了一个grad(就是梯度),当我们采用反向传播的时候,每一个节点(或者说每一个要更新的参数)都会求出来一个对应的梯度,在优化的过程中就可以根据这个梯度对其中的参数进行一个优化,最终以达到loss降低的目的。
梯度下降:如图二所示就是一个梯度下降,当前这个卷积核当中的一个参数处于最大圆球的位置,红色的曲线是整个的Loss Function,当我们采用反向传播的时候,就求出了最大圆球对应顶点的梯度。当我们进行更新时就可以根据梯度进行一个下降,进行一个参数的更新,最终以达到整个loss降低的功能。
图二:在这里插入图片描述
用代码来看一下我们如何采用反向传播? (这段代码其实就是前面的nn_loss_network.py中的代码,里面别的地方全都一样,只是把最后一行代码进行了一个修改)

from torch import nn
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.ensorboard import SummaryWriter#获取数据集
dataset = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
#加载数据到神经网络中去
dataloader = Dataloader(dataset,batch_size=1)class Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.model1 = Sequential(Conv2d(3,32,5,stride=1,padding=2),MaxPool2d(2),Conv2d(32,32,5,stride=1,padding=2),MaxPool2d(2),Conv2d(32,64,5,stride=1,padding=2),MaxPool2d(2),Flatten(),Linear(1024,64),Linear(64,10))def forward(self,x):x = self.model1 (x)return x#这种分类问题可以用前面介绍过的交叉熵进行loss的计算
loss = nn.CrossEntropyLoss()#初始化这个网络
feihan = Feihan()
for data in dataloader:imgs,targets = dataoutputs = feihan(imgs)#我们需要看一下outputs和targets长什么样,看选择什么样的损失函数#print(outputs)#print(targets)#运行结果格式类似于:#tensor([[-0.0731,0.0964,...]])括号里面有10个数字,每个代表预测是这个类别的概率#tensor([3])代表我们真实的targets是3result_loss = loss(outputs,targets)#反向传播result_loss.backward()

2 优化器

前面我们提到了反向传播,其中提到了当我们使用损失函数的时候我们可以调用损失函数的backward()函数得到反向传播。反向传播就可以求出我们每一个需要调节的参数,这个参数对应的一个梯度。有了这个梯度就可以利用优化器,让这个优化器根据这个梯度去进行调整,以达到整体误差降低的目的。

所有的优化器都是集中在torch.optim中。
用代码具体感受一下优化器的使用,具体代码示例如下所示:
nn_optim.py

from torch import nn
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.ensorboard import SummaryWriter#获取数据集
dataset = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
#加载数据到神经网络中去
dataloader = Dataloader(dataset,batch_size=1)class Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.model1 = Sequential(Conv2d(3,32,5,stride=1,padding=2),MaxPool2d(2),Conv2d(32,32,5,stride=1,padding=2),MaxPool2d(2),Conv2d(32,64,5,stride=1,padding=2),MaxPool2d(2),Flatten(),Linear(1024,64),Linear(64,10))def forward(self,x):x = self.model1 (x)return x#这种分类问题可以用前面介绍过的交叉熵进行loss的计算
loss = nn.CrossEntropyLoss()
#初始化这个网络
feihan = Feihan()
#设置优化器
#这里是以SGD梯度下降作为举例进行学习
#lr代表学习速率,一般不能设置的太大(太大的话模型训练起来很不稳定),也不能设置的太小(太小的话模型训练起来又比较慢)。一般情况下我们一开始采用比较大的学习速率来学习,学习到后面的时候采用比较小的学习速率来学习。
optim = torch.optim.SGD(feihan.parameters(),lr=0.01)
#定义了20轮循环过程
for epoch in range(20):#在每一轮开始之前都把loss设置成了0running_loss = 0.0#这是学习一轮所用的的循环,一般只循环一轮并不会有什么学习效果,所以我们需要在最外层再加一个循环for data in dataloader:imgs,targets = dataoutputs = feihan(imgs)result_loss = loss(outputs,targets)#把每一个网络模型当中每个可以调节参数对应的梯度调为0optim.zero_grad()#用优化器对参数进行优化#优化器需要每个参数的梯度,所以需要利用backward来得到#反向传播result_loss.backward()#调用优化器对每个参数进行一个调优optim.step()#每一轮学习过程中整体的一个loss的求和running_loss =  running_loss + result_lossprint(running_loss)

3 现有网络模型的使用及修改

下面将用vgg16这个模型进行举例讲解,注意一下:使用vgg16的前提是需要提前安装scipy这个包。
一个实例进行具体理解,对vgg16这个网络模型进行添加或修改操作:
model_pretrained.py

from torch import nn
import torchvision#仅加载网络模型,且网络模型中的参数都是初始化的,即默认的参数;不需下载。
vgg16_false = torchvision.models.vgg16(pretrained=False)
#不仅加载网络模型,且网络模型中的参数都是在ImageNet这个训练集上训练好的;仍需下载
vgg16_true = torchvision.models.vgg16(pretrained=True)print('ok')
print(vgg16_true )#获取数据集
train_data = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
#前面ImageNet这个训练集有1000种分类,而CIFAR10仅有10种分类,那么我们如何把现有的vgg16用到CIFAR10这个数据集当中去呢?应该如何进行修改?
#方法1:我们想在vgg16这个网络中添加一层,将Linear线性层中的in_features设置为1000,out_features设置为10即可。
vgg16_true.add_module('add_linear',nn.Linear(1000,10))
#或在vgg16这个网络的classifier层进行添加一层,将Linear线性层中的in_features设置为1000,out_features设置为10即可,具体代码如:vgg16_true.classifier.add_module('add_linear',nn.Linear(1000,10))
print(vgg16_true)#方法2:直接对vgg16这个网络进行修改,而不是添加。将Linear线性层中的out_features设置为10即可。
#由于前面我们已经对vgg16_true这个网络进行了一定的操作,下面我们就以vgg16_false进行演示
print(vgg16_false)
vgg16_false.classifier[6] = nn.Linear(4096,10)
print(vgg16_false)

4 网络模型的保存与读取

4.1 网络模型的保存

以vgg16模型的保存作为一个实例进行具体理解:
model_save.py

import torchvision
import torch
from torch import nnvgg16 = torchvision.models.vgg16(pretrained=False)
#保存方式1:模型结构+模型参数
#参数1:把vgg16这个网络模型放进去
#参数2:保存路径
torch.save(vgg16,"vgg16_method1.pth")
#这种方式不仅保存了网络模型的结构,还保存了网络模型的参数#保存方式2:模型参数(官方推荐)
#参数2:保存路径
torch.save(vgg16.state_dict(),"vgg16_method2.pth")
#这种方式把vgg16的状态保存成了一种字典形式,相当于把vgg16网络模型的参数保存成了字典。它不再保存网络模型的结构了,它保存网络模型当中的一些参数。#陷阱
#这里我们自己写了一个网络结构
class Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.conv1 = nn.Conv2d(3,64,kernel_size=3)def forward(self,x):x = self.conv1 (x)return x#初始化这个网络
feihan = Feihan()
#用方式1进行了保存
torch.save(feihan,"feihan_method1.pth")

4.2 网络模型的读取(加载)

再创建一个model_load.py文件来进行模型的加载。
model_load.py

import torch
import torchvision
from torch import nn
#与下面将class Feihan(nn.module):这个模型整个复制过来的操作一样,一般在这里进行一次性引用。复制和在这里一次性引用选一个即可。
from model_save import *#方式1(对应上面model_save.py中的保存方式1)加载模型
#参数:指定路径
model = torch.load("vgg16_method1.pth")
#print(model)#方式2(对应上面model_save.py中的保存方式2)加载模型
#参数:指定路径
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
#model = torch.load("vgg16_method2.pth")
#print(model)
#print(vgg16)#陷阱1
#因为用方式1进行的保存,所以对应用方式1进行加载
#如果这里不把模型的这个类引进来,则会报错,实现不了加载功能
#class Feihan(nn.module):#def __init__(self):#super(Feihan,self).__init__()#self.conv1 = nn.Conv2d(3,64,kernel_size=3)#def forward(self,x):#x = self.conv1 (x)#return xmodel = torch.load('feihan_method1.pth')
print(model)

5 完整的模型训练套路

以CIFAR10数据集作为一个例子,完成对数据集的分类问题。这个数据集之前讲过它有十个类别,也就是一个十分类的问题。
一个实例进行具体理解:
train.py

import torchvision
from torch.utils.data import DataLoader
from model import *
from torch import nn
from torch.utils.ensorboard import SummaryWriter#准备训练数据集
train_data = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
#准备测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)#数据集的长度
train_data_size = len(train_data)
test_data_size = len(test_data)
#如果train_data_size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))#利用DataLoader来加载数据集
train_dataloader = Dataloader(train_data,batch_size=64)
test_dataloader = Dataloader(test_data,batch_size=64)#搭建神经网络
#这个神经网络已经被单独写在了model.py文件中,需要使用时我们进行一个引用即可
#引用的代码:from model import *,一定要注意这个被引用的model文件夹和train这个文件夹要在同一个文件夹底下才行。#创建网络模型
feihan = Feihan()#损失函数
loss_fn = nn.CrossEntropyLoss()#优化器
learning_rate = 0.01
#还可以写成learning_rate = 1e-2
#1e-2=1*10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(feihan.parameters(),lr=learning_rate)#设置训练网络的一些参数
#记录训练的次数
total_train_step = 0
#记录测试的次数
total_test_step = 0
#训练的轮数
epoch = 10#添加tensorboard
writer = SummaryWrite("logs")for i in range(epoch):print("--------第 {} 轮训练开始-------".format(i+1))#训练步骤开始feihan.train()for data in train_dataloader:imgs,targets = dataoutputs = feihan(imgs)loss = loss_fn(outputs,targets)#优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()total_train_step = total_train_step + 1if total_train_step % 100 == 0:print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))writer.add_scalar("train_loss",loss.item(),total_train_step)#测试步骤开始feihan.eval()total_test_loss = 0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs,targets = dataoutputs = feihan(imgs)loss = loss_fn(outputs,targets)total_test_loss = total_test_loss + loss.item()#argmax(1)横向最大值;argmax(0)纵向最大值accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint("整体测试集上的Loss:{}".format(total_test_loss))print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss",total_test_loss,total_test_step)writer.add_scalar("test_accuracy",total_accuracy/test_data_size,total_test_step)total_test_step = total_test_step + 1torch.save(feihan,"feihan_{}.pth".format(i))#torch.save(feihan.state_dict(),"feihan_{}.pth".format(i))print("模型已保存")writer.close()

model.py

#搭建神经网络
from torch import nn
import torchclass Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.model = nn.Sequential(nn.Conv2d(3,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,64,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024,64),nn.Linear(64,10))def forward(self,x):x = self.model (x)return xif __name__ == '__main__':
#很多人一般喜欢在这里验证网络的正确性feihan = Feihan()input = torch.ones((64,3,32,32))output = feihan(input)print(output.shape)

6 利用GPU训练模型

如何使用GPU进行训练?其实使用GPU训练,我们只要在原来的代码修改几行就可以。我们仅需要关注网络模型、数据(输入、标注)、损失函数、.cuda()这几部分即可。但是GPU训练有两种方式,所以我们分别以具体的代码进行一个详细理解。
方式一(.cuda):
train_gpu_1.py

import torchvision
from torch.utils.data import DataLoader
#from model import *
from torch import nn
import torch
from torch.utils.ensorboard import SummaryWriter
#time是用来计时的
import time#准备训练数据集
train_data = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
#准备测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)#数据集的长度
train_data_size = len(train_data)
test_data_size = len(test_data)
#如果train_data_size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))#利用DataLoader来加载数据集
train_dataloader = Dataloader(train_data,batch_size=64)
test_dataloader = Dataloader(test_data,batch_size=64)#搭建神经网络
class Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.model = nn.Sequential(nn.Conv2d(3,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,64,5,stride=1,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#创建网络模型
feihan = Feihan()
#想利用GPU进行训练,所以转到cuda上面
if torch.cuda.is_available():feihan = feihan.cuda()#损失函数
loss_fn = nn.CrossEntropyLoss()
#想利用GPU进行训练,所以转到cuda上面
if torch.cuda.is_available():loss_fn = loss_fn.cuda()#优化器
learning_rate = 0.01
#还可以写成learning_rate = 1e-2
#1e-2=1*10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(feihan.parameters(),lr=learning_rate)#设置训练网络的一些参数
#记录训练的次数
total_train_step = 0
#记录测试的次数
total_test_step = 0
#训练的轮数
epoch = 10#添加tensorboard
writer = SummaryWrite("logs")
start_time = time.time()
for i in range(epoch):print("--------第 {} 轮训练开始-------".format(i+1))#训练步骤开始feihan.train()for data in train_dataloader:imgs,targets = data#想利用GPU进行训练,所以转到cuda上面if torch.cuda.is_available():imgs = imgs.cuda()targets = targets.cuda()outputs = feihan(imgs)loss = loss_fn(outputs,targets)#优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()total_train_step = total_train_step + 1if total_train_step % 100 == 0:end_time = time.time()print(end_time - start_time)print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))writer.add_scalar("train_loss",loss.item(),total_train_step)#测试步骤开始feihan.eval()total_test_loss = 0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs,targets = data#想利用GPU进行训练,所以转到cuda上面if torch.cuda.is_available():imgs = imgs.cuda()targets = targets.cuda()outputs = feihan(imgs)loss = loss_fn(outputs,targets)total_test_loss = total_test_loss + loss.item()#argmax(1)横向最大值;argmax(0)纵向最大值accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint("整体测试集上的Loss:{}".format(total_test_loss))print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss",total_test_loss,total_test_step)writer.add_scalar("test_accuracy",total_accuracy/test_data_size,total_test_step)total_test_step = total_test_step + 1torch.save(feihan,"feihan_{}.pth".format(i))#torch.save(feihan.state_dict(),"feihan_{}.pth".format(i))print("模型已保存")writer.close()

方式二(.to):
train_gpu_2.py

import torchvision
from torch.utils.data import DataLoader
#from model import *
from torch import nn
import torch
from torch.utils.ensorboard import SummaryWriter
#time是用来计时的
import time#定义训练设备
device = torch.device("cuda")
#device = torch.device("cuda:0")#但显卡
#device = torch.device("cuda:1")#双显卡
#device = torch.device("cuda" if torch.cuda.is_available() else "cpu")#如果没有cuda,用cpu
#这四种写法都是常见的,为了适应各种环境#准备训练数据集
train_data = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
#准备测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)#数据集的长度
train_data_size = len(train_data)
test_data_size = len(test_data)
#如果train_data_size=10,训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))#利用DataLoader来加载数据集
train_dataloader = Dataloader(train_data,batch_size=64)
test_dataloader = Dataloader(test_data,batch_size=64)#搭建神经网络
class Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.model = nn.Sequential(nn.Conv2d(3,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,64,5,stride=1,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#创建网络模型
feihan = Feihan()
#相当于把我们的网络转移到我们定义的设备当中去
feihan = feihan.to(device)#损失函数
loss_fn = nn.CrossEntropyLoss()
#相当于把我们的损失函数转移到我们定义的设备当中去
loss_fn = loss_fn.to(device)#优化器
learning_rate = 0.01
#还可以写成learning_rate = 1e-2
#1e-2=1*10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(feihan.parameters(),lr=learning_rate)#设置训练网络的一些参数
#记录训练的次数
total_train_step = 0
#记录测试的次数
total_test_step = 0
#训练的轮数
epoch = 10#添加tensorboard
writer = SummaryWrite("logs")
start_time = time.time()
for i in range(epoch):print("--------第 {} 轮训练开始-------".format(i+1))#训练步骤开始feihan.train()for data in train_dataloader:imgs,targets = data#相当于把我们的数据转移到我们定义的设备当中去imgs = imgs.to(device)targets = targets.to(device)outputs = feihan(imgs)loss = loss_fn(outputs,targets)#优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()total_train_step = total_train_step + 1if total_train_step % 100 == 0:end_time = time.time()print(end_time - start_time)print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))writer.add_scalar("train_loss",loss.item(),total_train_step)#测试步骤开始feihan.eval()total_test_loss = 0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs,targets = data#相当于把我们的数据转移到我们定义的设备当中去imgs = imgs.to(device)targets = targets.to(device)outputs = feihan(imgs)loss = loss_fn(outputs,targets)total_test_loss = total_test_loss + loss.item()#argmax(1)横向最大值;argmax(0)纵向最大值accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint("整体测试集上的Loss:{}".format(total_test_loss))print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss",total_test_loss,total_test_step)writer.add_scalar("test_accuracy",total_accuracy/test_data_size,total_test_step)total_test_step = total_test_step + 1torch.save(feihan,"feihan_{}.pth".format(i))#torch.save(feihan.state_dict(),"feihan_{}.pth".format(i))print("模型已保存")writer.close()

7 完整的模型验证套路:

完整的模型验证(测试、demo)套路:利用已经训练好的模型,然后给它提供输入。
一个实例进行具体理解:
test.py

from PIL import Image
import torchvision
from torch import nnimage_path = "../imgs/dog.png"
image = Image.open(image_path)
print(image)#因为png格式是四个通道,出来rgb三通道外,还有一个透明度通道。所以我们调用image = image.convert('RGB'),保留其通道颜色。
#当然,如果图片本来就是三通道,则不需要进行此操作。
image = image.convert('RGB')transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),torchvision.transforms.ToTensor()])image = transform(image)
print(image.shape)class Feihan(nn.module)def __init__(self)super(Feihan,self).__init__()self.model = nn.Sequential(nn.Conv2d(3,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,32,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Conv2d(32,64,5,stride=1,padding=2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024,64),nn.Linear(64,10))def forward(self,x):x = self.model (x)return xmodel = torch.load("feihan_0.pth")
#如果运行报错,我们可以修改为这样:model = torch.load("feihan_0.pth",map_location=torch.device('cpu'))
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))

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

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

相关文章

gitee创建仓库并上传代码实操记录

1、创建demo库 2、复制地址 3、下载到本地 4、复制文件至demo文件夹下 5、设置忽略文件 编辑文件.gitignore 替换为: # Created by .ignore support plugin (hsz.mobi) /target/* !.mvn/wrapper/maven-wrapper.jar src/test/ ### STS ### .apt_generated .clas…

java maven项目打jar包发布(精简版)

目录 一、maven打包 二、安装jdk环境 三、安装mysql 四、jar包传输到服务器 一、maven打包 先clean再package target文件夹下面有生成一个jar包 二、安装jdk环境 1、下载jdk cd /usr/local wget https://repo.huaweicloud.com/java/jdk/8u201-b09/jdk-8u201-linux-x64.tar.…

MySQL——基础——外连接

一、外连接查询语法:(实际开发中,左外连接的使用频率要高于右外连接) 左外连接 SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件...; 相当于查询表1(左表)的所有数据 包含 表1和表2交集部分的数据 右外连接 SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN …

linux-shell编程

shell编程 1. 变量、条件判断、流程控制、函数 $n (功能描述:n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}) $# &…

openCV实战-系列教程5:边缘检测(Canny边缘检测/高斯滤波器/Sobel算子/非极大值抑制/线性插值法/梯度方向/双阈值检测 )、原理解析、源码解读

打印一个图片可以做出一个函数: def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 1、Canny边缘检测流程 Canny是一个科学家在1986年写了一篇论文,所以用自己的名字来命名这个检测算法,Canny边缘检测算法…

Android应用启动流程:从启动到可交互的过程解析

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读1.1 启动知识储备1.2 Zygote进程1.3 SystemServer进程1.4 …

淘宝API技术解析,实现按图搜索淘宝商品

淘宝提供了开放平台接口(API)来实现按图搜索淘宝商品的功能。您可以通过以下步骤来实现: 1. 获取开放平台的访问权限:首先,您需要在淘宝开放平台创建一个应用,获取访问淘宝API的权限。具体的申请步骤和要求…

【分析绘图】R语言实现一些常见的绘图

微生信-在线绘图网站 线性图 library(ggplot2)x <- rnorm(100, 14, 5) # rnorm(n, mean 0, sd 1) y <- x rnorm(100, 0, 1) ggplot(data NULL, aes(x x, y y)) # 开始绘图geom_point(color "darkred") # 添加点annotate("text",x 13,…

JSON简介及前端简单解析(一)

JSON现在常用来做前后端数据交互&#xff0c;两个蝴蝶飞只是简单的对JSON做一下讲解和简单使用。关于JSON,我还了解的远远不够。由于本人经验有限&#xff0c;嘴皮子不溜&#xff0c;所以学术性&#xff0c;概念性&#xff0c;底层性的知识点暂时不做介绍。文章中有错误之处&am…

Android6:片段和导航

创建项目Secret Message strings.xml <resources><string name"app_name">Secret Message</string><string name"welcome_text">Welcome to the Secret Message app!Use this app to encrypt a secret message.Click on the Star…

飞天使-k8s基础组件分析-持久化存储

文章目录 emptyDirhostpathpv和pvc介绍nfs作为静态pv案例nfs作为动态pv案例使用本地文件夹作为pv改变默认存储类及回收策略参考文档 emptyDir 重启文件还有&#xff0c;但是如果杀了进程&#xff0c;则会丢失文件 创建pod # kubectl apply –f redis.yaml校验pod是否处于运行&…

基于CentOS搭建私有仓库harbor

环境&#xff1a; 操作系统&#xff1a;CentOS Linux 7 (Core) 内核&#xff1a; Linux 3.10.0-1160.el7.x86_64 目录 安装搭建harbor &#xff08;1&#xff09;安装docker编排工具docker compose &#xff08;2&#xff09;下载Harbor 安装包 &#xff08;3&…