【深度学习】LeNet原理及代码实现

news2024/10/1 7:43:41

目录

1.原理及介绍 

2.代码实现

2.1model.py

2.2model_train.py

2.3model.test.py


1.原理及介绍 

2.代码实现

2.1model.py

import torch
from torch import nn
from torchsummary import summary


class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        # 定义第一层卷积(in_channels;输入通道;out_channels:输出通道;kernel_size:卷积核大小;stride:步长,默认为1;padding:填充,默认为0)
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1, padding=2)
        self.sig = nn.Sigmoid()  # 激活函数
        self.pool1 = nn.AvgPool2d(kernel_size=2, stride=2)  # 第一次池化
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)  # 定义第二层卷积
        self.pool2 = nn.AvgPool2d(kernel_size=2, stride=2)  # 第二次池化

        self.flatten = nn.Flatten()  # 平展操作
        self.fc1 = nn.Linear(5 * 5 * 16, 120)  # 第一个全连接层
        self.fc2 = nn.Linear(120, 84)  # 第二个全连接层
        self.fc3 = nn.Linear(84, 10)  # 第三个全连接层

    def forward(self, x):
        x = self.conv1(x)
        x = self.sig(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = self.sig(x)
        x = self.pool2(x)
        x = self.flatten(x)
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x


if __name__ == "__main__":
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = LeNet().to(device)
    print(summary(model, (1, 28, 28)))  # 打印模型信息

2.2model_train.py

import copy
import time
import torch
import torch.nn as nn
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import torch.utils.data as data
from torchvision.datasets import FashionMNIST
from torchvision import transforms
from model import LeNet


def train_val_data_process():
    train_dataset = FashionMNIST(
        root='./data',  # 指定下载文件夹
        train=True,  # 只下载训练集
        # 归一化处理数据集
        transform=transforms.Compose([transforms.Resize(size=28),
                                      transforms.ToTensor()]),  # 数据转换成张量形式,方便模型应用
        download=True  # 下载数据
    )
    # 划分训练集和验证集
    train_data, val_data = data.random_split(train_dataset,
                                             [round(0.8 * len(train_dataset)), round(0.2 * len(train_dataset))])
    # 训练集加载
    train_dataloader = data.DataLoader(dataset=train_data,
                                       batch_size=32,  # 一个批次数据的数量
                                       shuffle=True,  # 数据打乱
                                       num_workers=2)  # 分配的进程数目
    # 验证集加载
    val_dataloader = data.DataLoader(dataset=val_data,
                                     batch_size=32,
                                     shuffle=True,
                                     num_workers=2)
    return train_dataloader, val_dataloader


def train_model_process(model, train_dataloader, val_dataloader, num_epochs):
    # 定义训练使用的设备,有GPU则用,没有则用CPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    # 使用Adam优化器进行模型参数更新,学习率为0.001
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    # 损失函数为交叉熵损失函数
    criterion = nn.CrossEntropyLoss()
    # 将模型放入训练设备内
    model = model.to(device)
    # 复制当前模型参数(w,b等),以便将最好的模型参数权重保存下来
    best_model_wts = copy.deepcopy(model.state_dict())

    # 初始化参数
    # 最高准确度
    best_acc = 0.0
    # 训练集损失值列表
    train_loss_all = []
    # 验证集损失值列表
    val_loss_all = []
    # 训练集准确度列表
    train_acc_all = []
    # 验证集准确度列表
    val_acc_all = []
    # 当前时间
    since = time.time()

    for epoch in range(num_epochs):
        print("Epoch {}/{}".format(epoch, num_epochs - 1))
        print("-" * 10)

        # 初始化参数
        # 训练集损失值
        train_loss = 0.0
        # 训练集精确度
        train_corrects = 0
        # 验证集损失值
        val_loss = 0.0
        # 验证集精确度
        val_corrects = 0
        # 训练集样本数量
        train_num = 0
        # 验证集样本数量
        val_num = 0

        # 对每一个mini-batch训练和计算
        for step, (b_x, b_y) in enumerate(train_dataloader):
            # 将特征放入到训练设备中
            b_x = b_x.to(device)  # batch_size*28*28*1的tensor数据
            # 将标签放入到训练设备中
            b_y = b_y.to(device)  # batch_size大小的向量tensor数据
            # 设置模型为训练模式
            model.train()

            # 前向传播过程,输入为一个batch,输出为一个batch中对应的预测
            output = model(b_x)  # 输出为:batch_size大小的行和10列组成的矩阵
            # 查找每一行中最大值对应的行标
            pre_lab = torch.argmax(output, dim=1)  # batch_size大小的向量表示属于物品的标签
            # 计算每一个batch的损失函数,向量形式的交叉熵损失函数
            loss = criterion(output, b_y)

            # 将梯度初始化为0,防止梯度累积
            optimizer.zero_grad()
            # 反向传播计算
            loss.backward()
            # 根据网络反向传播的梯度信息来更新网络的参数,以起到降低loss函数计算值的作用
            optimizer.step()
            # 对损失函数进行累加,该批次的loss值乘于该批次数量得到批次总体loss值,在将其累加得到轮次总体loss值
            train_loss += loss.item() * b_x.size(0)
            # 如果预测正确,则准确度train_corrects加1
            train_corrects += torch.sum(pre_lab == b_y.data)
            # 当前用于训练的样本数量
            train_num += b_x.size(0)

        for step, (b_x, b_y) in enumerate(val_dataloader):
            # 将特征放入到验证设备中
            b_x = b_x.to(device)
            # 将标签放入到验证设备中
            b_y = b_y.to(device)
            # 设置模型为评估模式
            model.eval()
            # 前向传播过程,输入为一个batch,输出为一个batch中对应的预测
            output = model(b_x)
            # 查找每一行中最大值对应的行标
            pre_lab = torch.argmax(output, dim=1)
            # 计算每一个batch的损失函数
            loss = criterion(output, b_y)

            # 对损失函数进行累加
            val_loss += loss.item() * b_x.size(0)
            # 如果预测正确,则准确度val_corrects加1
            val_corrects += torch.sum(pre_lab == b_y.data)
            # 当前用于验证的样本数量
            val_num += b_x.size(0)

        # 计算并保存每一轮次迭代的loss值和准确率
        # 计算并保存训练集的loss值
        train_loss_all.append(train_loss / train_num)
        # 计算并保存训练集的准确率
        train_acc_all.append(train_corrects.double().item() / train_num)
        # 计算并保存验证集的loss值
        val_loss_all.append(val_loss / val_num)
        # 计算并保存验证集的准确率
        val_acc_all.append(val_corrects.double().item() / val_num)

        # 打印每一轮次的loss值和准确度
        print("{} train loss:{:.4f} train acc: {:.4f}".format(epoch, train_loss_all[-1], train_acc_all[-1]))
        print("{} val loss:{:.4f} val acc: {:.4f}".format(epoch, 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_use = time.time() - since
        print("训练和验证耗费的时间{:.0f}m{:.0f}s".format(time_use // 60, time_use % 60))

    # 选择最优参数,保存最优参数的模型
    torch.save(best_model_wts, "./model_save/LeNet_best_model.pth")

    # 将产生的数据保存成表格,方便查看
    train_process = pd.DataFrame(data={"epoch": range(num_epochs),
                                       "train_loss_all": train_loss_all,
                                       "val_loss_all": val_loss_all,
                                       "train_acc_all": train_acc_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)  # 表示一行两列的第一张图
    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.xlabel("epoch")
    plt.ylabel("acc")
    plt.legend()
    plt.show()


if __name__ == '__main__':
    # 加载需要的模型
    LeNet = LeNet()
    # 加载数据集
    train_data, val_data = train_val_data_process()
    # 利用现有的模型进行模型的训练
    train_process = train_model_process(LeNet, train_data, val_data, num_epochs=20)
    matplot_acc_loss(train_process)

2.3model.test.py

import torch
import torch.utils.data as data
from torchvision import transforms
from torchvision.datasets import FashionMNIST
from model import LeNet


def test_data_process():
    test_data = FashionMNIST(root='./data',
                             train=False,  # 用测试集进行测试
                             transform=transforms.Compose([transforms.Resize(size=28), transforms.ToTensor()]),
                             download=True)

    test_dataloader = data.DataLoader(dataset=test_data,
                                      batch_size=1,  # 该批次设为1
                                      shuffle=True,
                                      num_workers=0)
    return test_dataloader


def test_model_process(model, test_dataloader):
    # 设定测试所用到的设备,有GPU用GPU没有GPU用CPU
    device = "cuda" if torch.cuda.is_available() else 'cpu'

    # 讲模型放入到训练设备中
    model = model.to(device)

    # 初始化参数
    test_corrects = 0.0
    test_num = 0

    # 只进行前向传播计算,不计算梯度,从而节省内存,加快运行速度
    with torch.no_grad():
        for test_data_x, test_data_y in test_dataloader:
            # 将特征放入到测试设备中
            test_data_x = test_data_x.to(device)
            # 将标签放入到测试设备中
            test_data_y = test_data_y.to(device)
            # 设置模型为评估模式
            model.eval()
            # 前向传播过程,输入为测试数据集,输出为对每个样本的预测值
            output = model(test_data_x)
            # 查找每一行中最大值对应的行标
            pre_lab = torch.argmax(output, dim=1)
            # 如果预测正确,则准确度test_corrects加1
            test_corrects += torch.sum(pre_lab == test_data_y.data)
            # 将所有的测试样本进行累加
            test_num += test_data_x.size(0)

    # 计算测试准确率
    test_acc = test_corrects.double().item() / test_num
    print("测试的准确率为:", test_acc)


if __name__ == "__main__":
    # 加载模型
    model = LeNet()
    model.load_state_dict(torch.load('./model_save/LeNet_best_model.pth'))  # 调用训练好的参数权重
    # 加载测试数据
    test_dataloader = test_data_process()
    # 加载模型测试的函数
    test_model_process(model, test_dataloader)

可以点个免费的赞吗!!!   

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

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

相关文章

高智能土壤养分检测仪:农业生产的科技新助力

在科技日新月异的今天,农业领域也迎来了革命性的变革。其中,高智能土壤养分检测仪作为现代农业的科技新助力,正逐渐改变着传统的农业生产方式,为农民带来了前所未有的便利与效益。 高智能土壤养分检测仪,是一款集高科技…

grep对文件内容搜索(附重要拓展-正则表达式)

文件搜索是搜索查找符合条件的某文件的目录,若要编辑文件或对文件的某配置进行修改,就需要对文件内容进行搜索。 grep 命令是 Linux 及类 Unix 操作系统中的一个强大的文本搜索工具,用于搜索一个或多个文件中匹配给定模式的行。grep 代表“Gl…

深入剖析数据库索引

写在前面: 此博客内容已经同步到我的博客网站,如需要获得更优的阅读体验请前往https://mainjaylai.github.io/Blog/blog/database 文章目录 如何验证我们正在使用InnoDB引擎 主键如果你没有自己创建任何主键会发生什么?关键字和索引之间的区别…

基于SpringBoot+Hadoop+python的物品租赁系统(带1w+文档)

基于SpringBootHadooppython的物品租赁系统(带1w文档) 基于SpringBootHadooppython的物品租赁系统(带1w文档) 物品租赁系统是电子、信息技术相结合,是一种必然的发展趋势。以互联网为基础,以服务于广大用户为目的,发展整体优势,扩…

经典双通道比较器LM393、LM393B、LM2903B、LM193、LM293和LM2903介绍及输入输出仿真

前言: LM393 SOP8封装的外观与丝印 LM393出现几十年了,是一款经典的双比较器,非常经典,用的比较多,新的比较器大家也要多关注。 该类型比较器,虽然静态电流较小,但在电池电路中耗电是巨大的&…

学习笔记——动态路由——IS-IS中间系统到中间系统(IS-IS工作过程)

六、IS-IS工作过程 1、第一步:建立邻居关系 IS-IS网络中所有路由器之间实现通信,主要通过以下几个步骤: (1)邻居关系建立: 邻居关系建立主要是通过HELLO包交互并协商各种参数,包括链路类型(level-1/level-2)&#…

hdfs大规模数据存储底层原理详解(第31天)

系列文章目录 一、HDFS设计原理 二、HDFS系统架构 三、HDFS关键技术 四、HDFS应用实例 五、解决HDFS不能处理小文件详解问题 文章目录 系列文章目录前言一、设计原理二、系统架构三、关键技术四、应用实例五、解决HDFS不能处理小文件详解问题1. 合并小文件2. 优化Hive配置3. 使…

乐器培训课程报名小程序模板源码

模板介绍 一款实用的音乐课程,乐器培训,艺术类网页课程报名手机小程序模板下载。包含:主页、列表、个人中心、报名等模块。 图片演示 乐器培训课程报名小程序模板源码

Oracle基础以及一些‘方言’(一)

1、什么是Oracle ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。 ORACLE 通常应用于大型系统的数据库产品。 ORACLE 数据库是目前世界…

免费试用Aicbo AI绘图软件,你的艺术梦想触手可及

最近AI绘图技术风靡全球,今天要给大家推荐一款集成了免费试用AI绘图软件的神器,即便你是从零开始,也能迅速掌握,创作出令人惊叹的艺术作品。平台是叫:Aicbo 这款神器设计人性化,操作极其简便,只…

apache:the requested operation has failed使用httpd -t

Apache24\bin cmd 回车 httpd -t 因为我重新压缩了,记住,重新压缩要使用原路径, 因为你安装的 时候使用的是原路径 还是不行就改个端口,切记修改配置文件httpd.conf先把Tomcat停了 Define SRVROOT "F:\Apache\Apache24&q…

相机光学(三十)——N5-N7-N8中性灰

GTI可提供N5/N7/N8中性灰涂料,用于不同的看色环境,N5/N7/N8代表深中浅不同的灰色程度,在成像、工业、印刷行业中,分别对周围观察环境有一定的要求,也出台了相应的标准文件,客户可以根据实际使用环境进行选择…

7.9实验室总结 SceneBuilder的使用方法+使用javafx等

由于下错了东西,所以一直运行不出来,今天一直在配置环境,配置好了才学,所以没学多少,看了网课学习了SceneBuilder的使用方法还有了解了javafx是怎么写项目的,, 学习了怎么跳转页面:…

ctfshow-web入门-文件上传(web164、web165)图片二次渲染绕过

web164 和 web165 的利用点都是二次渲染,一个是 png,一个是 jpg 目录 1、web164 2、web165 二次渲染: 网站服务器会对上传的图片进行二次处理,对文件内容进行替换更新,根据原有图片生成一个新的图片,这样…

效果惊人!LivePortrait开源数字人技术,让静态照片生动起来

不得了了,快手已经不是众人所知的那个短视频娱乐平台了。 可灵AI视频的风口尚未过去,又推出了LivePortrait--开源的数字人项目。LivePortrait让你的照片动起来,合成逼真的动态人像视频,阿里通义EMO不再是唯一选择。 让图像动起来 LivePortrait 主要提供了对眼睛和嘴唇动作的…

免费下载工具 -- Free Download Manager(FDM) v6.24.0.5818

软件简介 Free Download Manager (FDM) 是一款免费的功能强大的下载管理软件,适用于多种操作系统,包括 Windows、macOS、Android 和 Linux。这款软件的特色在于它快速、安全且高效的下载能力。它可以下载各种热门网站的影片,支持 HTTP/HTTP…

申请商标用什么颜色:企业和个人申请注册商标攻略!

在申请注册商标到底要用什么颜色,许多初次申请注册主体都不是特别清楚,普推知产商标老杨建议,在一般情况下建议尽量用黑白色,因为商标用黑白色在使用时可以着任何色。 在用黑色申请注册成功,别的主体用其它颜色要在同…

宝塔面板运行Admin.net框架

准备 宝塔安装 .netcore安装 Admin.net框架发布 宝塔面板设置 完结撒花 1.准备 服务器/虚拟机一台 系统Windows server / Ubuntu20.04(本贴使用的是Ubuntu20.04版本系统) Admin.net开发框架 先安装好服务器系统,这里就不做安装过程描述了&…

802.11漫游流程简单解析与笔记_Part2_05_wpa_supplicant如何通过nl80211控制内核开始关联

最近在进行和802.11漫游有关的工作,需要对wpa_supplicant认证流程和漫游过程有更多的了解,所以通过阅读论文等方式,记录整理漫游相关知识。Part1将记录802.11漫游的基本流程、802.11R的基本流程、与认证和漫游都有关的三层秘钥基础。Part1将包…

读人工智能全传08人工智能的今天

1. 人工智能的今天 1.1. 未来,或许有些领域会有非常明显的人工智能痕迹,有些领域则不会 1.2. 2018年,来自计算机视觉处理器公司英伟达的研究人员证明了人工智能软件能够创造出虚假的人物照片,并且能够完全…