搭建LeNet-5神经网络,并搭建自己的图像分类训练和测试的模板,模板通用!!!均有详细注释。

ops/2024/10/21 0:53:29/

本文任务:

1、构建LeNet神经网络

2、搭建图像分类训练和测试的通用模板。

3、训练出自己的模型。

4、验证模型效果。

LeNet论文地址:原文地址icon-default.png?t=O83Ahttp://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf


目录

一、LeNet-5神经网络介绍

1、网络结构

2、网络分析

(1)最初研究目的

(2)组成部分

(3)数据传输过程

(4)网络参数

(5)总结

二、代码实现LeNet-5神经网络

1、构建LeNet神经网络

2、搭建图像分类训练的通用模板

3、搭建图像分类测试的通用模板

4、训练出自己的模型

5、验证模型效果

三、调试好的源码


一、LeNet-5神经网络介绍

1、网络结构

该网络比较简单,由两个卷积层两个平池化层三个全连接层组成。

流程:输入 => 卷积层 => 池化层 => 卷积层 => 池化层 => 全连接层 * 3

2、网络分析

(1)最初研究目的

        手写数字识别。

(2)组成部分

        特征提取部分:由两个卷积层和两个平均池化层组成。

        全连接层:由三个全连接层促成。

(3)数据传输过程

(4)网络参数

        下图是输入图像(以1*28*28的图像为例)经过网络每个层之后的变化。

        最后一个全连接层可以用来确定我们需要分类的种类,例如我们的数据集一共是10个种类,那最后一个全连接层我们就需要设置输出特征值为10

(5)总结

        LeNet使用了非线性激活函数sigmoid来进行寻找最优参数,它是最早发布的卷积神经网络之一,具有开创意义,学习这个入门卷积神经网络是大多数初学者的选择。

二、代码实现LeNet-5神经网络

我的项目目录如下:

其中,fashion_data文件夹是我们的数据集,这个数据集是PyTorch中自带的数据集,大家直接运行我下面的model_train.py就可以自动下载,或者大家也可以自行下载,model文件夹是我用来存放训练好的模型的,这个大家可以自行设置存放路径。

以下代码均有详细注释,所以不在这里讲解。

1、构建LeNet神经网络

        model.py

# LeNet神经网络
import torch
from torch import nn
from torchsummary import summaryclass LeNet(nn.Module):def __init__(self):super(LeNet, self).__init__()self.model = nn.Sequential(nn.Conv2d(1, 6, 5, padding=2, stride=1),nn.Sigmoid(),  # 激活函数nn.AvgPool2d(2, stride=2), # 平均池化nn.Conv2d(6, 16, 5),nn.Sigmoid(),  # 激活函数nn.AvgPool2d(2, stride=2),nn.Flatten(),  # 平展层,将数据降成一维nn.Linear(16 * 5 * 5, 120),nn.Linear(120, 84),nn.Linear(84, 10)  # 映射到10个输出,10个输出对应的就是10个不同的数字类别(0到9)的概率分布。)# 前向传播函数def forward(self, x):x = self.model(x)return xif __name__ == '__main__':# 指定设备device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 将模型放到gpu中model = LeNet().to(device)# 测试网络是否能正常使用print(summary(model, (1, 28, 28)))

2、搭建图像分类训练的通用模板

        model_train.py

import copy
import time
import torch
from torchvision import transforms
from torchvision.datasets import FashionMNIST
import numpy as np
import matplotlib.pyplot as plt
from model import LeNet
import torch.utils.data as Data
import torch.nn as nn
import pandas as pd# 加载数据集
def train_val_data_process():# 加载数据集,没下载的会自动下载数据集train_data = FashionMNIST(root='./fashion_data',train=True,download=True,transform=transforms.Compose([transforms.Resize(size=28), transforms.ToTensor()]))# 划分训练集、验证集train_data, val_data = Data.random_split(train_data, [round(0.8 * len(train_data)), round(0.2 * len(train_data))])train_loader = Data.DataLoader(dataset=train_data, batch_size=128, shuffle=True, num_workers=0)val_loader = Data.DataLoader(dataset=val_data, batch_size=128, shuffle=True, num_workers=0)return train_loader, val_loader# 训练过程
def train_model_process(model, train_loader, val_loader, epochs):device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 定义优化器,使用Adam优化器,学习率为0.001optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 交叉熵损失函数loss_fn = nn.CrossEntropyLoss()# 将模型放入到训练设备当中model = model.to(device)# 复制当前模型的参数best_model_wts = copy.deepcopy(model.state_dict())# 初始化参数# 初始化精度best_acc = 0.0# 保存训练集loss值的列表train_loss_all = []# 保存验证集loss值的列表val_loss_all = []# 保存训练集精度的列表train_acc_all = []# 保存验证集精度的列表val_acc_all = []# 保存当前时间since = time.time()for epoch in range(epochs):print('Epoch {}/{}'.format(epoch + 1, epochs))print('-' * 10)# 初始化参数# 训练集train_loss = 0.0train_acc = 0.0# 验证集val_loss = 0.0val_acc = 0.0# 训练集的样本数量train_num = 0# 验证集的样本数量val_num = 0# 对每一个batch进行训练for step, (images, labels) in enumerate(train_loader):# 将特征和标签放到gpu中images, labels = images.to(device), labels.to(device)# 设置模型为训练模式model.train()# 将数据放入到模型当中,向前传播过程,输入为一个batch,输出为一个batch中对应的预测outputs = model(images)# 查找每一行中最大值对应的行标pre_labels = torch.argmax(outputs, dim=1)# 计算损失loss = loss_fn(outputs, labels)# 将梯度清0optimizer.zero_grad()# 反向传播计算loss.backward()# 根据网络反向传播的梯度信息来更新网络的参数,以起到降低loss函数计算值的作用optimizer.step()# 对损失函数进行累加train_loss += loss.item() * images.size(0)# 计算准确的数量train_acc += torch.sum(pre_labels == labels.data)# 当前用于训练的样本数量train_num += images.size(0)# 验证开始with torch.no_grad():for step, (images, labels) in enumerate(val_loader):# 将特征和标签放到gpu中images, labels = images.to(device), labels.to(device)# 设置模型为验证模式model.eval()# 前向传播outputs = model(images)# 查找每一行中最大值对应的行标pre_labels = torch.argmax(outputs, dim=1)# 计算损失loss = loss_fn(outputs, labels)# 对损失函数进行累加val_loss += loss.item() * images.size(0)# 计算准确的数量val_acc += torch.sum(pre_labels == labels.data)# 当前用于验证的样本数量val_num += images.size(0)# 计算每一次迭代的loss值和准确率train_loss_all.append(train_loss / train_num)train_acc_all.append(train_acc.double().item() / train_num)val_loss_all.append(val_loss / val_num)val_acc_all.append(val_acc.double().item() / val_num)# 打印出每轮的训练损失值和训练准确率print('{} Train Loss: {:.4f} Train Acc: {:.4f}'.format(epoch + 1, train_loss_all[-1], train_acc_all[-1]))# 打印出每轮的验证损失值和验证准确率print('{} Val Loss: {:.4f} Val Acc: {:.4f}'.format(epoch + 1, val_loss_all[-1], val_acc_all[-1]))# 寻找最高准确度的权重if val_acc_all[-1] > best_acc:best_acc = val_acc_all[-1]# 保存当前的最优参数best_model_wts = copy.deepcopy(model.state_dict())# 计算该轮次训练所花费的时间time_used = time.time() - sinceprint('训练和验证花费的时间:{:.0f}m{:.0f}s'.format(time_used // 60, time_used % 60))# 选择最优模型# 加载最优的模型参数torch.save(best_model_wts, './model/model.pth')# 训练过程的数据train_process = pd.DataFrame(data={'epoch': range(epochs),'train_loss_all': train_loss_all,'train_acc_all': train_acc_all,'val_loss_all': val_loss_all,'val_acc_all': val_acc_all})return train_process# 画图
def matplot_acc_loss(train_process):plt.figure(figsize=(12, 4))plt.subplot(1, 2, 1) # 一行两列的第一张图# loss图plt.plot(train_process['epoch'], train_process['train_loss_all'], 'ro-', label='train loss')plt.plot(train_process['epoch'], train_process['val_loss_all'], 'bs-', label='val loss')plt.legend()plt.xlabel('Epoch')plt.ylabel('Loss')plt.subplot(1, 2, 2) # 一行两列的第二张图plt.plot(train_process['epoch'], train_process['train_acc_all'], 'ro-', label='train acc')plt.plot(train_process['epoch'], train_process['val_acc_all'], 'bs-',label='val acc')plt.legend()plt.xlabel('Epoch')plt.ylabel('Accuracy')plt.show()if __name__ == '__main__':# 将模型实例化leNet = LeNet()train_loader, val_loader = train_val_data_process()train_process = train_model_process(leNet, train_loader, val_loader, 50) # 50代表训练的轮次matplot_acc_loss(train_process)

3、搭建图像分类测试的通用模板

        model_test.py

import torch
from torchvision import transforms
import torchvision
import torch.utils.data as Data
from torchvision.datasets import FashionMNIST
from model import LeNet# 加载测试集
def test_val_data_process():test_data = FashionMNIST(root='./fashion_data',train=False,download=True,transform=transforms.Compose([transforms.Resize(size=28), transforms.ToTensor()]))test_loader = Data.DataLoader(dataset=test_data, batch_size=1, shuffle=True, num_workers=0)return test_loader# 开始测试模型
def test_model_process(model, test_loader):# 设置测试环境device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 将模型放入到gpu中model = model.to(device)# 初始化参数# 模型的测试精度test_accuracy = 0.0# 用来记录测试次数test_num = 0# 只进行前向传播,不计算梯度,从而节省内存,加快运算速度with torch.no_grad():for images, labels in test_loader:# 加载数据集到gpu中images, labels = images.to(device), labels.to(device)# 设置模型为评估模式model.eval()# 进行前向传播output = model(images)# 查找最大值对应的行标pred_lab = output.argmax(dim=1, keepdim=True)# 计算测试正确的数据个数test_accuracy += torch.sum(pred_lab == labels.data)# 计算测试样本总数test_num += images.size(0)# 计算准确率test_acc = test_accuracy.double() / test_numprint("测试的准确率为:",test_acc)return test_accif __name__ == '__main__':model = LeNet()# 加载我们前面训练好的权重model.load_state_dict(torch.load('./model/model.pth'))test_loader = test_val_data_process()test_acc = test_model_process(model, test_loader)

4、训练出自己的模型

我们运行model_train.py文件,来进行模型的训练。

由于时间原因,我这里只训练了20轮,大家在实际运行时,可以把轮次设置的大一些,这样得到的模型效果会更好。

输出:

我使用的是gpu训练的,我的显卡是RTX4060Ti,训练了20轮,总花费是1分11秒,大家可以根据自己的显卡来设置训练的轮数和训练批次的大小。

我训练好的模型保存在了model文件夹下:

5、验证模型效果

接下来我们来使用我们上面训练好的模型来对验证数据集进行推理,为了节约时间,进攻显示,我们使用的测试数据集和上述训练数据集是一致的(实际操作中不要这样进行,推理使用的数据一般是未经过训练的),所以我们可以直接开始运行model_test.py来验证我们的模型效果。

 可以看到,测试的准确率是85.73%,对于我们训练20轮次来说,效果还不错,那么我们整个训练,推理的过程就结束了,希望大家可以动手试一下,有问题请在评论区提问哦。

三、调试好的源码

我这边提供给大家一个我调试好的源码,方便新手进行训练、测试。

大家扫码关注公众号,回复关键字LeNet源码即可获取。


http://www.ppmy.cn/ops/127131.html

相关文章

爬虫逆向学习(十二):一个案例入门补环境

此分享只用于学习用途,不作商业用途,若有冒犯,请联系处理 反爬前置信息 站点:aHR0cDovLzEyMC4yMTEuMTExLjIwNjo4MDkwL3hqendkdC94anp3ZHQvcGFnZXMvaW5mby9wb2xpY3k 接口:/xjzwdt/rest/xmzInfoDeliveryRest/getInfoDe…

git clone 鉴权失败

git clone 鉴权失败问题 1. 问题描述2. 解决方法 1. 问题描述 使用git clone自己的代码报如下错误: 正克隆到 xxx... Username for https://github.com: Password for https://xxxgithub.com: remote: Support for password authentication was removed on Augu…

【Flutter】页面布局:线性布局(Row 和 Column)

在 Flutter 中,布局(Layout)是应用开发的核心之一。通过布局组件,开发者可以定义应用中的控件如何在屏幕上排列。Row 和 Column 是 Flutter 中最常用的两种线性布局方式,用于水平和垂直排列子组件。在本教程中&#xf…

Unity中通过给定的顶点数组生成凸面体的方法参考

这里我们使用了Quickhull for Unity插件,其实就是一个ConvexHullCalculator.cs文件,代码如下: /*** Copyright 2019 Oskar Sigvardsson** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software…

部署服务dockerfile失败小记

首先是碰到在ENTRYPOINT 中添加参数问题,一时懵逼直接添加到最后 ENTRYPOINT [“java”,“-jar”,“xx-xx.jar”,“–spring.profiles.active${envType}”,“–add-opens java.base/java.langALL-UNNAMED”,“–add-opens java.base/java.utilALL-UNNAMED”, “–a…

PHP政务招商系统——高效连接共筑发展蓝图

政务招商系统——高效连接,共筑发展蓝图 🏛️ 一、政务招商系统:开启智慧招商新篇章 在当今经济全球化的背景下,政务招商成为了推动地方经济发展的重要引擎。而政务招商系统的出现,更是为这一进程注入了新的活力。它…

设计模式(c++)

设计模式通常分为三大类: 创建型模式(Creational Patterns):负责对象创建的机制,主要解决对象创建过程中的复杂性和灵活性问题。 结构型模式(Structural Patterns):负责处理类或对象…

PythonExcel批量pingIP地址

问题: 作为一个电气工程师(PLC),当设备掉线的时候,需要用ping工具来检查网线物理层是否可靠连接,当项目体量过大时,就不能一个手动输入命令了。 解决方案一: 使用CMD命令 for /L %…