赞
踩
阿里云开发者社区:https://developer.aliyun.com/article/1196254?spm=a2c6h.13148508.setting.14.21a54f0eQRsFIB
微信公众号:https://mp.weixin.qq.com/s?__biz=MzIwOTc2MTUyMg==&mid=2247530266&idx=1&sn=7da4a8f0334d3028bbe6b8c020684dd9&chksm=976cd287a01b5b912a20e03c58b09199a8cb4869c09a40320301fc22a494de86fc673475527e&token=431225665&lang=zh_CN#rd
GitHub代码、数据:https://github.com/RedstoneWill/ObjectDetectionLearner/tree/main/LeNet-5
三者皆为同一人所写。
torch.optim是PyTorch中用于实现各种优化算法的模块,在训练神经网络时非常有用。
它提供了各种类型的优化器,如随机梯度下降、Adam、Adagrad等,并允许我们根据需要自定义优化器。
我们可以使用各种类型的优化器来更新神经网络模型的参数。
tochvision主要处理图像数据,包含一些常用的数据集、模型、转换函数等。
torchvision主要包含以下四部分:
torchvision.models: 提供深度学习中各种经典的网络结构、预训练好的模型,如:Alex-Net、VGG、ResNet、Inception等。
torchvision.datasets:提供常用的数据集,设计上继承 torch.utils.data.Dataset,主要包括:MNIST、CIFAR10/100、ImageNet、COCO等。
torchvision.transforms:提供常用的数据预处理操作,主要包括对Tensor及PIL Image对象的操作。
torchvision.utils:工具类,如保存张量作为图像到磁盘,给一个小批量创建一个图像网格。
原文链接:https://blog.csdn.net/qq_45772756/article/details/128651447
torchvision 的 transforms 集成了随机翻转、旋转、增强对比度、
转化为tensor、转化为图像等功能,用于数据增强,非常便捷
原文链接:https://blog.csdn.net/iteapoy/article/details/106121752
标准化系数就是计算要用到的均值和标准差,在本例中是((0.1307,), (0.3081,)),均值是 0.1307,标准差是 0.3081,这些系数都是数据集提供方计算好的数据。不同数据集就有不同的标准化系数,另外还需要保持train_set、val_set和test_set标准化系数的一致性。
其实在torch里面,view函数就相当于numpy的reshape,执行的操作就是对tensor进行维度转换。这边的这里-1表示一个不确定的数,就是你如果不确定你想要reshape成几行
解决方法:因为是从model.py文件中调用的LeNet,所以应该在test.py文件中导入model.py文件中对应的LeNet类即可。即from model import LeNet
运行且识别成功。以下面的图片为例:
识别结果:
文件结构:(data文件运行代码时会自动生成,images文件是放测试识别图片的文件夹,models是存放训练的模型的权重的文件夹)
model.py的代码如下:
import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim """torch.optim是PyTorch中用于实现各种优化算法的模块,在训练神经网络时非常有用。 它提供了各种类型的优化器,如随机梯度下降、Adam、Adagrad等,并允许我们根据需要自定义优化器。 我们可以使用各种类型的优化器来更新神经网络模型的参数。""" from torchvision import datasets,transforms """tochvision主要处理图像数据,包含一些常用的数据集、模型、转换函数等。 torchvision主要包含以下四部分: torchvision.models: 提供深度学习中各种经典的网络结构、预训练好的模型,如:Alex-Net、VGG、ResNet、Inception等。 torchvision.datasets:提供常用的数据集,设计上继承 torch.utils.data.Dataset,主要包括:MNIST、CIFAR10/100、ImageNet、COCO等。 torchvision.transforms:提供常用的数据预处理操作,主要包括对Tensor及PIL Image对象的操作。 torchvision.utils:工具类,如保存张量作为图像到磁盘,给一个小批量创建一个图像网格。 原文链接:https://blog.csdn.net/qq_45772756/article/details/128651447 torchvision 的 transforms 集成了随机翻转、旋转、增强对比度、 转化为tensor、转化为图像等功能,用于数据增强,非常便捷 原文链接:https://blog.csdn.net/iteapoy/article/details/106121752""" import time from matplotlib import pyplot as plt pipline_train=transforms.Compose([ #随机旋转图片 transforms.RandomHorizontalFlip(), #将图片尺寸resize到32*32 transforms.Resize((32,32)), #将图片转化为Tensor格式 transforms.ToTensor(), #正则化(当模型出现过拟合的情况时,用来降低模型的复杂度) transforms.Normalize((0.1307,),(0.3081,)) ]) """标准化系数就是计算要用到的均值和标准差,在本例中是((0.1307,), (0.3081,)), 均值是 0.1307,标准差是 0.3081,这些系数都是数据集提供方计算好的数据。 不同数据集就有不同的标准化系数,另外还需要保持train_set、val_set和test_set标准化系数的一致性""" pipline_test=transforms.Compose([ # 将图片尺寸resize到32*32 transforms.Resize((32, 32)), transforms.ToTensor(), transforms.Normalize((0.1307,),(0.3081,)) ]) #下载数据集 train_set=datasets.MNIST(root="./data",train=True,download=True,transform=pipline_train) test_set=datasets.MNIST(root="./data",train=False,download=True,transform=pipline_test) #加载数据集 trainloader=torch.utils.data.DataLoader(train_set,batch_size=64,shuffle=True) testloader=torch.utils.data.DataLoader(test_set,batch_size=32,shuffle=False) #搭建LeNet-5网络 class LeNet(nn.Module): def __init__(self): super(LeNet, self).__init__() #定义激活函数,方便下面的使用 self.relu=nn.ReLU() # 创建卷积和池化层 # 创建第一个卷积层 self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5) # kernel_size=5代表5*5的卷积核 self.maxpool1 = nn.MaxPool2d(kernel_size=2, stride=2) # 在池化层中步长和池化的窗口大小一致 # 尺寸的逻辑:池化层未改变通道数;当前通道数为6 # 创建第二个卷积层 self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5) self.maxpool2 = nn.MaxPool2d(kernel_size=2, stride=2) #创建三个全连接层 #第一个全连接层的输出神经元个数为120, 第三个全连接层输出神经元个数为分类标签的类别数 self.fc1 = nn.Linear(in_features=16*5*5, out_features=120) self.fc2 = nn.Linear(in_features=120, out_features=84) self.fc3 = nn.Linear(in_features=84, out_features=10) def forward(self, x): x=self.conv1(x) x=self.relu(x) x=self.maxpool1(x) x=self.conv2(x) x=self.relu(x) x=self.maxpool2(x) x=x.view(-1,16*5*5) # 使用view函数展平成一维向量 """其实在torch里面,view函数就相当于numpy的reshape, 执行的操作就是对tensor进行维度转换。这边的这里-1代表自动调整这个维度上的元素个数,以保证元素的总数不变""" x=F.relu(self.fc1(x)) x=F.relu(self.fc2(x)) x=self.fc3(x) output=F.log_softmax(x,dim=1) """对softmax的结果进行log,log_softmax解决函数overflow和underflow,加快运算速度,提高数据稳性定。防止溢出. dim=0:对每一列的所有元素进行softmax运算,并使得每一列所有元素和为1。 dim=1:对每一行的所有元素进行softmax运算,并使得每一行所有元素和为1。""" return output #创建模型,部署gpu device=torch.device("cuda" if torch.cuda.is_available() else "cpu") model=LeNet().to(device) #定义优化器 optimizer=optim.Adam(model.parameters(),lr=0.001) #定义训练过程 def train_runner(model,device,trainloader,optimizer,epoch): #训练模型,启用BatchNormalization和Dropout,将BatchNormalization和Dropout置为True model.train() total=0 correct=0.0 #enumerate迭代已加载的数据集,同时获取数据和数据下标 for i,data in enumerate(trainloader,0): #train_loader是一个数据加载器,0是一个可选参数,用于指定枚举对象的起始索引。 """enumerate()用于可迭代、可遍历的数据对象组合为一个索引序列,同时列出数据和数据下标, 上面代码的0表示从索引从0开始,假如为1的话,那索引就从1开始. data里面包含图像数据(inputs)(tensor类型的)和标签(labels)(tensor类型)。""" inputs,labels=data #把模型部署到device上 inputs,labels=inputs.to(device),labels.to(device) #初始化梯度,将优化器的梯度清零,以便在下一次迭代中计算新的梯度。 optimizer.zero_grad() #保存训练结果 outputs=model(inputs) #计算损失和 #多分类情况通常使用cross_entropy(交叉熵损失函数), 而对于二分类问题, 通常使用sigmoid loss=F.cross_entropy(outputs,labels) #获取最大概率的预测结果 #dim=1表示返回每一行的最大值对应的下标 predict=outputs.argmax(dim=1) #累加总样本数和正确预测的样本数。 total+=labels.size(0) #size()主要是用来统计矩阵元素个数,或矩阵某一维上的元素个数的函数。 correct+=(predict==labels).sum().item() #反向传播 loss.backward() #使用优化器更新模型参数 optimizer.step() if i%1000==0: # loss.item()表示当前loss的数值 print("Train Epoch{} \t Loss:{:.6f},accuracy:{:.6f}%".format(epoch,loss.item(),100*(correct/total))) Loss.append(loss.item()) Accuracy.append(correct/total) return loss.item(),correct/total #定义测试过程 def test_runner(model,device,testloader): # 模型验证, 必须要写, 否则只要有输入数据, 即使不训练, 它也会改变权值 # 因为调用eval()将不启用 BatchNormalization 和 Dropout, BatchNormalization和Dropout置为False model.eval() #统计模型正确率,设置初始值 correct=0.0 test_loss=0.0 total=0 #torch.no_grad将不会计算梯度,也不会进行反向传播 with torch.no_grad(): for data,label in testloader: data,label=data.to(device),label.to(device) output=model(data) test_loss+=F.cross_entropy(output,label).item() predict=output.argmax(dim=1) #计算正确数量 total+=label.size(0) correct+=(predict==label).sum().item() #计算损失值 print("test_avarage_loss:{:.6f},accuracy: {:.6f}%".format(test_loss/total, 100*(correct/total))) #开始运行 epoch=5 Loss=[] Accuracy=[] for epoch in range(1,epoch+1): print("start_time",time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))) loss,acc=train_runner(model,device,trainloader,optimizer,epoch) Loss.append(loss) Accuracy.append(acc) test_runner(model,device,testloader) print("end_time: ",time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),'\n') print('Finished Training') plt.subplot(2,1,1) """plt.subplot(2, 1, 1)是matplotlib.pyplot库中的一个函数,用于在一张图中创建多个子图。这个函数的参数表示子图的布局和当前激活的子图。 在这个例子中,`2` 表示子图的行数,`1` 表示子图的列数,`1` 表示当前激活的子图索引。因此,这行代码将创建一个包含两行一列子图的图,并激活第一个子图""" plt.plot(Loss) plt.title('Loss') plt.show() plt.subplot(2,1,2) plt.plot(Accuracy) plt.title('Accuracy') plt.show() #保存模型 print(model) torch.save(model,'./models/models-mnist.pth')
test.py的代码如下:
import cv2 import matplotlib.pyplot as plt import torch import torch.nn.functional as F from torchvision import datasets,transforms from model import LeNet if __name__=='__main__': device=torch.device('cuda' if torch.cuda.is_available() else 'cpu') model=torch.load('./models/models-mnist.pth') model=model.to(device) model.eval() #把模型转为test模式 #读取要预测的图片 img=cv2.imread("./images/5_5.jpg") img=cv2.resize(img,dsize=(32,32),interpolation=cv2.INTER_NEAREST) plt.axis('off')#不显示坐标 plt.show() #导入图片,图片扩展后为[1,1,32,32] trans=transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#图片转为灰度图,因为mnist数据集都是灰度图 img=trans(img) img=img.to(device) img=img.unsqueeze(0) #图片扩展多一维,因为输入到保存的模型中是4维的[batch_size,通道,长,宽],而普通图片只有三维,[通道,长,宽] #预测 output=model(img) prob=F.softmax(output,dim=1)#prob是10个分类的概率 print("概率:",prob) value,predicted=torch.max(output.data,1) predict=output.argmax(dim=1) print("预测类别:",predict.item())
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。