基于CIFAR10的图片识别

news2024/11/14 23:33:20

前言

这个算是重拾一个古早项目了,当时搭建神经网络对CIFAR10数据集进行训练以后,对训练好的网络进行了验证,可以参考这笔者的两篇博客:

pytorch 模型训练(以CIFAR10数据集为例)_pytorch cifar10-CSDN博客

pytorch模型验证(以CIFAR10数据集为例)_单独摘取cifar10数据集的汽车进行验证-CSDN博客

这次我将当初的CNN换成了LeNet,并且使用Pyside6编写了一个简单的UI以方便对训练好的模型的验证。

代码部分

得到训练好的网络

import numpy as np
import torch
import torchvision
from torch import nn
from torch.utils.data import TensorDataset  # TensorDataset可以用来对tensor数据进行打包,该类中的 tensor 第一维度必须相等(即每一个图片对应一个标签)
from torch.utils.data import DataLoader
from torch.optim import lr_scheduler
import matplotlib.pyplot as plt
import scipy.io
import torch.nn.functional as F
from sklearn.metrics import confusion_matrix

if torch.cuda.is_available():
    device=torch.device("cuda")
else:
    device=torch.device("cpu")

# mean = [0.5070751592371323, 0.48654887331495095, 0.4409178433670343]
# std = [0.2673342858792401, 0.2564384629170883, 0.27615047132568404]

# transforms_fn=torchvision.transforms.Compose([
#     torchvision.transforms.RandomCrop(size=32,padding=4), #扩充为40*40,然后随机裁剪成32*32
#     torchvision.transforms.RandomHorizontalFlip(0.5),
#     torchvision.transforms.ToTensor(),
#     torchvision.transforms.Normalize(mean, std)
# ])
transforms_fn=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

#准备数据集
#训练数据集
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)

# print(type(train_data))

#获取2个数据集的长度
train_data_size=len(train_data)
test_data_size=len(test_data)
print("训练数据集的长度为{}".format(train_data_size))
print("测试数据集的长度为{}".format(test_data_size))

#利用dataloader来加载数据集
train=DataLoader(train_data,batch_size=64, shuffle=True)
test=DataLoader(test_data,batch_size=64)

#搭建神经网络
#in_channels=3,out_channels=32,kernel_size=5,stride=1,padding=2(padding:是否会在图片旁边进行填充)
class LeNet(nn.Module):                     # 继承于nn.Module这个父类
    def __init__(self):                     # 初始化网络结构
        super(LeNet, self).__init__()       # 多继承需用到super函数
        self.conv1 = nn.Conv2d(3, 16, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 32, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(32*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):			 # 正向传播过程
        x = F.relu(self.conv1(x))    # input(3, 32, 32) output(16, 28, 28)
        x = self.pool1(x)            # output(16, 14, 14)
        x = F.relu(self.conv2(x))    # output(32, 10, 10)
        x = self.pool2(x)            # output(32, 5, 5)
        x = x.view(-1, 32*5*5)       # output(32*5*5)
        x = F.relu(self.fc1(x))      # output(120)
        x = F.relu(self.fc2(x))      # output(84)
        x = self.fc3(x)              # output(10)
        return x

softmax=nn.Softmax() #在计算准确率时还是要加上Softmax的

model=LeNet()
model.to(device)
loss_fn = nn.CrossEntropyLoss()
loss_fn.to(device)
learning_rate = 0.001

# 注意,1.如果用SGD优化器,一般学习率大一点,如0.1、0.05;Adam优化器学习率可以小一点,如0.001、0.0001
#      2.最好加上weight_decay和学习率衰减
# optimizer=torch.optim.SGD(params=model.parameters(),lr=learning_rate,momentum=0.5,weight_decay=0.01)
optimizer=torch.optim.Adam(params=model.parameters(),lr=learning_rate) # weight_decay越大,会进行惩罚,降低变化的速率,一般优化器中的参数都为默认值
# scheduler=lr_scheduler.ExponentialLR(optimizer,gamma=0.94) #学习率衰减(指数衰减),gamma不要设置的太小

train_acc_list = []
train_loss_list = []
test_acc_list = []
test_loss_list = []
epochs = 15


#开始训练+测试
for epoch in range(epochs):


    print("-----第{}轮训练开始------".format(epoch + 1))
    train_loss = 0.0
    test_loss = 0.0
    train_sum, train_cor, test_sum, test_cor = 0, 0, 0, 0
    # arr=np.zeros((1,3630))
    test_label=[]
    test_pred=[]

    # 训练步骤开始
    model.train()
    for batch_idx, data in enumerate(train):
        inputs, labels = data
        inputs, labels=inputs.to(device),labels.to(device)

        # labels = torch.tensor(labels, dtype=torch.long)  # 需要将label转换成long类型
        optimizer.zero_grad()
        outputs = model(inputs)  # 需要加.float(),否则会报错
        loss = loss_fn(outputs, labels)
        loss.backward()
        optimizer.step()

        # 计算每轮训练集的Loss
        train_loss += loss.item()

        # 计算每轮训练集的准确度
        outputs = softmax(outputs)  # 计算准确率时需要添加softmax
        _, predicted = torch.max(outputs.data, 1)  # 选择最大的(概率)值所在的列数就是他所对应的类别数,
        train_cor += (predicted == labels).sum().item()  # 正确分类个数
        train_sum += labels.size(0)  # train_sum+=predicted.shape[0]
    # scheduler.step()
        # train_true.append(labels.cpu().numpy()) #想把CUDA tensor格式的数据改成numpy时,需要先将其转换成cpu float-tensor随后再转到numpy格式。 numpy不能读取CUDA tensor 需要先将它转化为 CPU tensor
        # train_pred.append(predicted.cpu().numpy())

    # 测试步骤开始
    # model.eval()
    # with torch.no_grad(): #即使一个tensor(命名为x)的requires_grad = True,在with torch.no_grad计算,由x得到的新tensor(命名为w-标量)requires_grad也为False,且grad_fn也为None,即不会对w求导。
    #     for batch_idx1, data in enumerate(test):
    #         inputs, labels = data
    #         inputs, labels = inputs.to(device), labels.to(device)
    #         # labels = torch.tensor(labels, dtype=torch.long)
    #
    #         outputs = model(inputs)
    #         loss = loss_fn(outputs, labels)
    #
    #         # 计算每轮训练集的Loss
    #         test_loss += loss.item()
    #
    #         # 计算每轮训练集的准确度
    #         outputs = softmax(outputs)  # 计算准确率时需要添加softmax
    #         _, predicted = torch.max(outputs.data, 1)
    #         test_cor += (predicted == labels).sum().item()
    #         test_sum += labels.size(0)
    #         # print(predicted)
    #         # print(labels)
    #
    #         # test_label = test_label + list(labels.cpu().numpy())
    #         # test_pred = test_pred + list(predicted.cpu().numpy())
    #
    #
    print("Train loss:{}   Train accuracy:{}%".format(train_loss / batch_idx, 100 * train_cor / train_sum))
    train_loss_list.append(train_loss / batch_idx)
    train_acc_list.append(100 * train_cor / train_sum)
    # test_acc_list.append(100 * test_cor / test_sum)
    # test_loss_list.append(test_loss / batch_idx1)

# 保存网络
torch.save(model.state_dict(), "CIFAR10_{}.pth".format(epochs)) #model.state_dict保存模型参数、超参数以及优化器的状态信息
# torch.save(model, "CIFAR10_{}.pth".format(epochs))


#输出混淆矩阵
# print(len(test_label))
# print(len(test_pred))
# # print(test_label)
# test_true=list(test_label.numpy())
# # print(test_true)
# # print(test_pred)
# # print(type(test_true))
# # print(type(test_pred))
#
# test_true=np.array(test_true) #强制转换为numpy的array形式
# test_pred=np.array(test_pred)
#
# print(test_true)
# print(test_pred)
# print(test_true.shape)
# print(test_pred.shape)
#
# C=confusion_matrix(test_true, test_pred) #混淆矩阵
# print(C)
# plt.matshow(C, cmap=plt.cm.Reds)
# plt.show()

#绘制曲线
# fig = plt.figure()
# plt.plot(range(len(train_loss_list)), train_loss_list, 'blue')
# plt.title('TrainLoss', fontsize=14)
# plt.xlabel('Epoch', fontsize=14)
# plt.ylabel('Loss', fontsize=14)
# plt.grid()
# plt.savefig('TrainLoss_HRRP')
# plt.show()
# fig = plt.figure()
# plt.plot(range(len(test_loss_list)), test_loss_list, 'red')
# plt.title('TestLoss', fontsize=14)
# plt.xlabel('Epoch', fontsize=14)
# plt.ylabel('Loss', fontsize=14)
# plt.grid()
# plt.savefig('TestLoss_HRRP')
# plt.show()

fig = plt.figure()
plt.plot(range(len(train_acc_list)), train_acc_list, 'blue')
plt.title('TrainAccuracy', fontsize=14)
plt.xlabel('Epoch', fontsize=14)
plt.ylabel('Accuracy(%)', fontsize=14)
plt.grid()
# plt.savefig('TrainAccuracy_HRRP')
plt.show()
# fig = plt.figure()
# plt.plot(range(len(test_acc_list)), test_acc_list, 'red')
# plt.title('TestAccuracy', fontsize=14)
# plt.xlabel('Epoch', fontsize=14)
# plt.ylabel('Accuracy(%)', fontsize=14)
# plt.grid()
# # plt.savefig('TestAccuracy_HRRP')
# plt.show()

编写单个图片输入进网络进行的函数

import numpy as np
import torch
import torchvision
from torch import nn
from torch.utils.data import TensorDataset  # TensorDataset可以用来对tensor数据进行打包,该类中的 tensor 第一维度必须相等(即每一个图片对应一个标签)
from torch.utils.data import DataLoader
from torch.optim import lr_scheduler
import matplotlib.pyplot as plt
import scipy.io
import torch.nn.functional as F
from sklearn.metrics import confusion_matrix
from PIL import Image

if torch.cuda.is_available():
    device=torch.device("cuda")
else:
    device=torch.device("cpu")

class LeNet(nn.Module):                     # 继承于nn.Module这个父类
    def __init__(self):                     # 初始化网络结构
        super(LeNet, self).__init__()       # 多继承需用到super函数
        self.conv1 = nn.Conv2d(3, 16, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 32, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(32*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):			 # 正向传播过程
        x = F.relu(self.conv1(x))    # input(3, 32, 32) output(16, 28, 28)
        x = self.pool1(x)            # output(16, 14, 14)
        x = F.relu(self.conv2(x))    # output(32, 10, 10)
        x = self.pool2(x)            # output(32, 5, 5)
        x = x.view(-1, 32*5*5)       # output(32*5*5)
        x = F.relu(self.fc1(x))      # output(120)
        x = F.relu(self.fc2(x))      # output(84)
        x = self.fc3(x)              # output(10)
        return x

softmax=nn.Softmax() #在计算准确率时还是要加上Softmax的

model=LeNet()
model_weight_pth='./Model_pth/CIFAR10_15.pth'
model.load_state_dict(torch.load(model_weight_pth)) #使用model.state_dict方式保存,则需要这样下载网络
model.to(device)
# print(model)

def rec_single_img(data_path):
    data=Image.open(data_path).resize((200,200))
    data = data.convert('RGB')
    transform = torchvision.transforms.Compose(
        [torchvision.transforms.Resize((32, 32)),  # 这里Resize是将图片的尺寸转为32*32,因为之前训练的网络对图片的要求就是32*32
         torchvision.transforms.ToTensor()])
    data=transform(data)
    data = torch.reshape(data, (1, 3, 32, 32))  # 需要的是4维数据,但图片是3维,用这行代码进行改写
    data = data.to(device)

    model.eval()
    with torch.no_grad():
        output = model(data)
        output = softmax(output)
        # _, predicted = torch.max(output.data, 1)
        label= output.data.max(1, keepdims=True)[1]
        classes = ('plane', 'car', 'bird', 'cat',
                   'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
        predicted=classes[label]


    return predicted

# predicted=rec_single_img('image1.jpg')
# print(predicted)

UI界面即逻辑调用

import numpy as np
import torch
import torchvision
from torch import nn
from torch.utils.data import TensorDataset  # TensorDataset可以用来对tensor数据进行打包,该类中的 tensor 第一维度必须相等(即每一个图片对应一个标签)
from torch.utils.data import DataLoader
from torch.optim import lr_scheduler
import matplotlib.pyplot as plt
import scipy.io
import torch.nn.functional as F
from sklearn.metrics import confusion_matrix
from PIL import Image
import scipy.io

from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QTableWidgetItem, QFileDialog
from PySide6.QtGui import QFont, QPixmap
from UI.rec_UI import Ui_Form

from model_test import rec_single_img


# pyside6-uic rec_UI.ui -o rec_UI.py

class recWindow(QWidget, Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.bind() #绑定函数

    def bind(self):
        self.pushButton.clicked.connect(self.recognize)
        self.pushButton_2.clicked.connect(self.draw)
        self.pushButton_3.clicked.connect(self.clear)

    def recognize(self):
        img_path=self.lineEdit.text()
        pred=rec_single_img(img_path)
        self.lineEdit_2.setText(pred)


    def draw(self):
        img_path = self.lineEdit.text()
        self.label_3.setScaledContents(True)  # 设置缩放,即图片可自适应Label的大小
        self.label_3.setPixmap(QPixmap(img_path))

    def clear(self):
        self.lineEdit.clear()
        self.lineEdit_2.clear()
        self.label_3.clear()


if __name__ == '__main__':
    app=QApplication([])
    window=recWindow()
    window.show()
    app.exec()


运行结果

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CAPL使用结构体的方式组装一条DoIP车辆声明消息(方法2)

在文章CAPL使用结构体的方式组装一条DoIP车辆声明消息(方法1)中,我们声明一个结构体DoIPMessage表示完整的DoIP车辆声明消息: 上半部分是DoIP报头通用部分(也就是所有类型的DoIP消息都有的),而payload是每个类型的DoIP消息独有的部分,对于车辆声明消息来说,用另一个结…

Golang | Leetcode Golang题解之第309题买卖股票的最佳时机含冷冻期

题目&#xff1a; 题解&#xff1a; func maxProfit(prices []int) int {if len(prices) 0 {return 0}n : len(prices)f0, f1, f2 : -prices[0], 0, 0for i : 1; i < n; i {newf0 : max(f0, f2 - prices[i])newf1 : f0 prices[i]newf2 : max(f1, f2)f0, f1, f2 newf0, n…

【划分字母区间】python刷题记录

R3-贪心篇. 思路&#xff1a; 1.使用dict记录S中每个字符出现的最后位置 2.从s[0]开始&#xff0c;j该元素的dict值&#xff0c;遍历s&#xff0c;如果出现s[i]>j&#xff0c;就需要更新j的值 3.i到j了&#xff0c;那就下一段 class Solution:def partitionLabels(self,…

「Unity3D」自动布局LayoutElement、ContentSizeFitter、AspectRatioFitter、GridLayoutGroup

布局元素与布局控制器 布局元素实现ILayoutElement接口&#xff0c;布局控制器实现ILayoutController接口&#xff0c;后者根据前者的属性控制具体布局——有些布局控制器也是布局元素&#xff0c;即同时实现这两个接口&#xff0c;如LayoutGroup。 public interface ILayout…

【原创教程】电气电工:电烙铁的使用方法(入门)

今天我们深入了解电烙铁的相关知识及其应用。电烙铁作为电气电工行业中的重要工具&#xff0c;它在焊接和电路维修等方面扮演着不可或缺的角色。接下来&#xff0c;我们将一起探索电烙铁的奥秘。 一、电烙铁概述 电烙铁是一种通过电能转化为热能进行焊接的工具。它具有体积小…

jenkins服务器重启,构建记录消失

1、进入系统管理查看系统运行日志&#xff0c;发现报保存构建日志失败 jenkins module java.base does not "opens java.lang.ref" to unnamed module 5276d6ee Java平台模块系统对类的可见性和访问权限进行了严格的控制。在Java 9及以上版本中&#xff0c;java.la…

武汉流星汇聚:深耕跨境电商,万企信赖之选,共绘全球贸易新蓝图

在全球化浪潮汹涌的今天&#xff0c;跨境电商作为连接世界经济的桥梁&#xff0c;正以前所未有的速度改变着国际贸易的格局。在这场充满机遇的旅途中&#xff0c;武汉流星汇聚电子商务有限公司犹如一颗璀璨的流星&#xff0c;划破长空&#xff0c;以其卓越的实力和不懈的努力&a…

JetBrains:XML tag has empty body警告

在xml文件中配置时&#xff0c;因为标签内容为空&#xff0c;出现黄色警告影响观感。 通过IDE配置关闭告警

编程语言|Python——为什么0.1+0.2≠0.3(深入理解Python中的浮点数运算)

一、问题描述 技术面的时候被问到一个python问题,即当我们输入0.1+0.2时,打印出来的却不是0.3,而是0.30000000000000004,为什么? 其实不仅是Python,很多编程语言例如C、Java、JavaScript等等都有这种特性。原理很简单,所有数的运算在计算机中都是进行二进制计算的,十进…

RS485 转 Lora 模块

一、功能概述 本产品是一款无线中继器&#xff0c;将 RS485 信号转为无线信号&#xff0c;通过 无线方式远传&#xff0c;实现远程通信功能。采用 Lora无线通信技术&#xff0c;工作 中心频率 433M &#xff0c;空旷传输距离 7000 米。 二、接线、配置方法、指示灯状态 1 、…

【Python实战因果推断】63_随机实验与统计知识5

目录 Hypothesis Testing Null Hypothesis Hypothesis Testing 另一种引入不确定性的方法是陈述假设检验&#xff1a;两个组之间的均值差异是否在统计上与零&#xff08;或其他任何值&#xff09;不同&#xff1f;要回答这类问题&#xff0c;你需要回想正态分布的和或差也是正…

【Java算法专场】前缀和(上)

前言 在求数组或者矩阵求和等问题&#xff0c;我们如果采用暴力解法&#xff0c;时间复杂度可能会达到O(n)或者更高&#xff0c;因此&#xff0c;我们可利用前缀和来解决。 前缀和 前缀和是指序列中的n项和&#xff0c;相当于数学问题中秋数列的前n项和。主要用于数组或列表中…

[Bugku] web-CTF-POST

1.开启环境 2.根据题目得知使用POST传参&#xff0c;即可得到flag

[240802] 有关 Homebrew 的安全审核 | Running C++ anywhere like a script

目录 有关 Homebrew 的安全审核Running C anywhere like a script 有关 Homebrew 的安全审核 Trail of Bits 对 macOS 包管理工具 Homebrew 进行了安全审计&#xff0c;重点关注其核心代码库和 CI/CD 流程。审计发现了 Homebrew 中存在的一些问题&#xff0c;这些问题可能被攻…

来点八股文(四) 数据检索ESOLAPCK和Calcite

文章目录 压缩存储&索引codegen优化器向量化 如何解决深度分页问题&#xff1f; scoll 游标分页 使用的是快照&#xff0c;没法保证实时fromsize 最差的实现&#xff0c;内存占用和时间都很差search_after 搜索上下文 通过记录自增id来查询&#xff0c;减少了内存占用 luc…

GDAL——地理空间数据抽象库在VS2022下的编译

上图是GDAL在github上的首页截图&#xff0c;GDAL库本身是没法运行的(一开始想运行它看看&#xff0c;但后知后觉一个库单独怎么能运行呢哈哈哈哈哈哈)。编译成功后&#xff0c;会生成几个文件夹&#xff0c;里面有一些文件&#xff0c;把这些文件配置到合适的位置后&#xff0…

css-grid布局之美

一&#xff0c;grid布局概述 网格布局&#xff08;Grid&#xff09;是最强大的 CSS 布局方案。 它将网页划分成一个个网格&#xff0c;可以任意组合不同的网格&#xff0c;做出各种各样的布局。以前&#xff0c;只能通过复杂的 CSS 框架达到的效果&#xff0c;现在浏览器内置…

游戏加速器推荐 网游加速器排行榜

游戏加速器推荐&#xff0c;玩游戏用什么加速器&#xff01;我得给你推荐一款我常用的。首先呢&#xff0c;就是深度加速器&#xff0c;它针对目前手游网游的游戏加速效果特别棒&#xff0c;而且界面也很友好。 另外&#xff0c;还有深度加速器&#xff0c;这款加速器不仅支持国…

使用模版完成不同数据类型的数组的选择排序

目录 6.模版(167-263) 6.1函数模板 6.1.1函数模版注意事项 6.1.2函数模版案例--选择排序 1. 比较排序的基本概念 2. 决策树 3. 决策树的深度 4. 结论 5.选择排序示例: 6.模版(167-263) (项目先跳过) 模板不能直接使用,它只是一个框架. 模板不是万能的. 6.1函数模板…

HCIE还是CCIE?高级认证到底要怎么选?

HCIE与CCIE&#xff0c;作为网络技术领域的两大旗舰认证&#xff0c;一直是IT专业人士追求的目标。 它们不仅代表了个人技术能力的权威认可&#xff0c;更是职业生涯中的重要里程碑。 然而&#xff0c;面对这两个同为高级认证的金字招牌&#xff0c;许多人不禁要问&#xff1a;…