【利用pytorch搭建改进LeNet-5网络模型(win11)续】

本文涉及的产品
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
交互式建模 PAI-DSW,每月250计算时 3个月
模型训练 PAI-DLC,100CU*H 3个月
简介: 【利用pytorch搭建改进LeNet-5网络模型(win11)续】

本文基于利用pytorch搭建改进LeNet-5网络模型(win11)改进设计,添加打印网络结构和保存acc-loss可视化并保存,设计了LeNet-5和改进LeNet-5两种网络,对比分析可得改进LeNet-5两种网络准确度有一定的提升。

1. 前言

       手写字体识别模型LeNet5诞生于1994年,是最早的卷积神经网络之一。LeNet5通过巧妙的设计,利用卷积、参数共享、池化等操作提取特征,避免了大量的计算成本,最后再使用全连接神经网络进行分类识别,这个网络也是最近大量神经网络架构的起点。

1.png

代码分析见视频: 从0开始撸代码--手把手教你搭建LeNet-5网络模型

环境配置见:基于Anaconda安装pytorch和paddle深度学习环境(win11)

卷积或池化输出图像尺寸的计算公式如下:

O=输出图像的尺寸;I=输入图像的尺寸;K=池化或卷积层的核尺寸;S=移动步长;P =填充数

2. 程序

网路结构程序分为三部分net、train、main(test),下面分别介绍两种网络的代码

2.1 LeNet-5

net.py定义网络结构,初始化输入输出参数,网络模型命名为MyLet5

import torch
from torch import nn
from torchsummary import summary
# 定义一个网络模型类
class MyLeNet5(nn.Module):
    # 初始化网络
    def __init__(self):
        super(MyLeNet5, self).__init__()
        # 输入大小为32*32,输出大小为28*28,输入通道为1,输出为6,卷积核为5
        self.c1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, padding=2)
        # 使用sigmoid激活函数
        self.Sigmoid = nn.Sigmoid()
        # 使用平均池化
        self.s2 = nn.AvgPool2d(kernel_size=2, stride=2)
        self.c3 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)
        self.s4 = nn.AvgPool2d(kernel_size=2, stride=2)
#        self.c5 = nn.Conv2d(in_channels=16, out_channels=120, kernel_size=5)
#        self.flatten = nn.Flatten()
        self.f5 = nn.Linear(16*5*5, 120)
        self.f6 = nn.Linear(120, 84)
        self.output = nn.Linear(84, 10)
    def forward(self, x):
        # x输入为32*32*1, 输出为28*28*6
        x = self.Sigmoid(self.c1(x))
        # x输入为28*28*6, 输出为14*14*6
        x = self.s2(x)
        # x输入为14*14*6, 输出为10*10*16
        x = self.Sigmoid(self.c3(x))
        # x输入为10*10*16, 输出为5*5*16
        x = self.s4(x)
        # x输入为5*5*16, 输出为1*1*120
#        x = self.c5(x)
#        x = self.flatten(x)
#        x = self.f5(x)
        # x输入为120, 输出为84
#        x = self.f6(x)
        # x输入为84, 输出为10
        x = x.view(-1, 16 * 5 * 5)
        x = self.f5(x)
        x = self.f6(x)
        x = self.output(x)
        return x
if __name__ == "__main__":
    x = torch.rand([1, 1, 28, 28])
    model = MyLeNet5()
    y = model(x)
device = torch.device('cuda:0')
model = MyLeNet5()
model.to(device)
summary(model, (1, 28, 28))

可以右键run 一下,检验程序是否正确。就会打印网络结构

2.1.1.png

train.py数据转化为tensor格式,加载训练数据集,如果显卡可用,则用显卡进行训练,如果GPU可用则将模型转到GPU,定义损失函数,定义训练函数,定义验证函数,开始训练,这里为了节约时间只训练了20次。

import torch
from torch import nn
from net import MyLeNet5
from torch.optim import lr_scheduler
from torchvision import datasets, transforms
import os
# 将数据转化为tensor格式
data_transform = transforms.Compose([
    transforms.ToTensor()
])
# 加载训练数据集
train_dataset = datasets.MNIST(root='./data', train=True, transform=data_transform, download=True)
# 给训练集创建一个数据加载器, shuffle=True用于打乱数据集,每次都会以不同的顺序返回。
train_dataloader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=16, shuffle=True)
# 加载训练数据集
test_dataset = datasets.MNIST(root='./data', train=False, transform=data_transform, download=True)
# 给训练集创建一个数据加载器, shuffle=True用于打乱数据集,每次都会以不同的顺序返回。
test_dataloader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=16, shuffle=True)
# 如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else 'cpu'
# 调用net里面定义的模型,如果GPU可用则将模型转到GPU
model = MyLeNet5().to(device)
# 定义损失函数(交叉熵损失)
loss_fn = nn.CrossEntropyLoss()
# 定义优化器,SGD,
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3, momentum=0.9)
# 学习率每隔10epoch变为原来的0.1
lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
# 定义训练函数
def train(dataloader, model, loss_fn, optimizer):
    loss, current, n = 0.0, 0.0, 0
    # enumerate返回为数据和标签还有批次
    for batch, (X, y) in enumerate(dataloader):
        # 前向传播
        X, y = X.to(device), y.to(device)
        output = model(X)
        cur_loss = loss_fn(output, y)
        # torch.max返回每行最大的概率和最大概率的索引,由于批次是16,所以返回16个概率和索引
        _, pred = torch.max(output, axis=1)
        # 计算每批次的准确率, output.shape[0]为该批次的多少
        cur_acc = torch.sum(y == pred) / output.shape[0]
        # print(cur_acc)
        # 反向传播
        optimizer.zero_grad()
        cur_loss.backward()
        optimizer.step()
        # 取出loss值和精度值
        loss += cur_loss.item()
        current += cur_acc.item()
        n = n + 1
    print('train_loss' + str(loss / n))
    print('train_acc' + str(current / n))
# 定义验证函数
def val(dataloader, model, loss_fn):
    # 将模型转为验证模式
    model.eval()
    loss, current, n = 0.0, 0.0, 0
    # 非训练,推理期用到(测试时模型参数不用更新, 所以no_grad)
    # print(torch.no_grad)
    with torch.no_grad():
        for batch, (X, y) in enumerate(dataloader):
            X, y = X.to(device), y.to(device)
            output = model(X)
            cur_loss = loss_fn(output, y)
            _, pred = torch.max(output, axis=1)
            cur_acc = torch.sum(y == pred) / output.shape[0]
            loss += cur_loss.item()
            current += cur_acc.item()
            n = n + 1
        print('val_loss' + str(loss / n))
        print('val_acc' + str(current / n))
        return current / n
# 开始训练
epoch = 20
min_acc = 0
for t in range(epoch):
    lr_scheduler.step()
    print(f"epoch{t + 1}\n-------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    a = val(test_dataloader, model, loss_fn)
    # 保存最好的模型权重文件
    if a > min_acc:
        folder = 'sava_model'
        if not os.path.exists(folder):
            os.mkdir('sava_model')
        min_acc = a
        print('save best model', )
        torch.save(model.state_dict(), "sava_model/best_model.pth")
    # 保存最后的权重文件
    if t == epoch - 1:
        torch.save(model.state_dict(), "sava_model/last_model.pth")
print('Done!')

可以run(F5) 一下,得到最佳模型,精度达到了95.88%,还不错呦!

2.1.2.png

LeNet网络训练集和验证集acc精确度值对比图

2.1.3.png

LeNet网络训练集和验证集loss值对比图

2.1.4.png

2.2 改进LeNet-5

net1.py定义网络结构,初始化输入输出参数,网络模型命名为WR_MyLet5

import torch
from torch import nn
from torchsummary import summary
# 定义一个网络模型类
class WR_MyLeNet5(nn.Module):
    # 初始化网络
    def __init__(self):
        super(WR_MyLeNet5, self).__init__()
        # 输入大小为32*32,输出大小为28*28,输入通道为1,输出为6,卷积核为5
        self.c1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=9, padding=2)
        # 使用sigmoid激活函数
        self.Sigmoid = nn.Sigmoid()
        # 使用平均池化
        self.s2 = nn.AvgPool2d(kernel_size=2, stride=2)
        self.c3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5)
        self.s4 = nn.AvgPool2d(kernel_size=2, stride=2)
        self.c5 = nn.Conv2d(in_channels=64, out_channels=120, kernel_size=3)
        self.s6 = nn.AvgPool2d(kernel_size=2, stride=2)
        self.flatten = nn.Flatten()
        self.f7 = nn.Linear(120, 84)
        self.output = nn.Linear(84, 10)
    def forward(self, x):
        # x输入为32*32*1, 输出为28*28*6
        x = self.Sigmoid(self.c1(x))
        # x输入为28*28*6, 输出为14*14*6
        x = self.s2(x)
        # x输入为14*14*6, 输出为10*10*16
        x = self.Sigmoid(self.c3(x))
        # x输入为10*10*16, 输出为5*5*16
        x = self.s4(x)
        # x输入为5*5*16, 输出为1*1*120
        x = self.c5(x)
        x = self.s6(x)
        x = self.flatten(x)
        # x输入为120, 输出为84
        x = self.f7(x)
        # x输入为84, 输出为10
        x = self.output(x)
        return x
if __name__ == "__main__":
    x = torch.rand([1, 1, 28, 28])
    model = WR_MyLeNet5()
    y = model(x)
device = torch.device('cuda:0')
model = WR_MyLeNet5()
model.to(device)
summary(model, (1, 28, 28))

可以右键run 一下,检验程序是否正确。就会打印网络结构

2.2.1.png

可以run(F5) 一下,得到最佳模型,精度达到了95.96%,还不错呦!

2.2.2.png

LeNet网络训练集和验证集acc精确度值对比图

2.2.3.png

LeNet网络训练集和验证集loss值对比图

2.2.4.png

2.3 main

       数据转化为tensor格式,加载训练数据集,如果显卡可用,则用显卡进行训练,如果GPU可用则将模型转到GPU,加载 train.py 里训练好的模型,把tensor转成Image, 方便可视化,获取预测结果,进入验证阶段,测试前五张图片。

import torch
from net import MyLeNet5
from torch.autograd import Variable
from torchvision import datasets, transforms
from torchvision.transforms import ToPILImage
# 将数据转化为tensor格式
data_transform = transforms.Compose([
    transforms.ToTensor()
])
# 加载训练数据集
train_dataset = datasets.MNIST(root='./data', train=True, transform=data_transform, download=True)
# 给训练集创建一个数据加载器, shuffle=True用于打乱数据集,每次都会以不同的顺序返回。
train_dataloader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=16, shuffle=True)
# 加载训练数据集
test_dataset = datasets.MNIST(root='./data', train=False, transform=data_transform, download=True)
# 给训练集创建一个数据加载器, shuffle=True用于打乱数据集,每次都会以不同的顺序返回。
test_dataloader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=16, shuffle=True)
#  如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else 'cpu'
# 调用net里面定义的模型,如果GPU可用则将模型转到GPU
model = MyLeNet5().to(device)
# 加载 train.py 里训练好的模型
model.load_state_dict(torch.load("sava_model/best_model.pth"))
# 获取预测结果
classes = [
    "0",
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9",
]
# 把tensor转成Image, 方便可视化
show = ToPILImage()
# 进入验证阶段
model.eval()
# 对test_dataset里10000张手写数字图片进行推理
# for i in range(len(test_dataloader)):
for i in range(5):
    x, y = test_dataset[i][0], test_dataset[i][1]
    # tensor格式数据可视化
    show(x).show()
    # 扩展张量维度为4维
    x = Variable(torch.unsqueeze(x, dim=0).float(), requires_grad=False).to(device)
    with torch.no_grad():
        pred = model(x)
        # 得到预测类别中最高的那一类,再把最高的这一类对应classes中的哪一类标签
        predicted, actual = classes[torch.argmax(pred[0])], classes[y]
        # 最终输出的预测值与真实值
        print(f'predicted: "{predicted}", actual:"{actual}"')

2.3.1.png上面import需要修改为对应的网络结构,效果如下 ,全部都是正确的滴!

2.3.2.png

3. 总结

       本文介绍利用利用pytorch搭建改进LeNet-5网络模型(win11),接下来我会记录我的pytorch和paddle深度学习记录,很高兴能和大家分享!🤣🤣🤣希望你能有所收获。

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
2月前
|
算法 PyTorch 算法框架/工具
Pytorch学习笔记(九):Pytorch模型的FLOPs、模型参数量等信息输出(torchstat、thop、ptflops、torchsummary)
本文介绍了如何使用torchstat、thop、ptflops和torchsummary等工具来计算Pytorch模型的FLOPs、模型参数量等信息。
397 2
|
25天前
|
机器学习/深度学习 人工智能 PyTorch
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
本文探讨了Transformer模型中变长输入序列的优化策略,旨在解决深度学习中常见的计算效率问题。文章首先介绍了批处理变长输入的技术挑战,特别是填充方法导致的资源浪费。随后,提出了多种优化技术,包括动态填充、PyTorch NestedTensors、FlashAttention2和XFormers的memory_efficient_attention。这些技术通过减少冗余计算、优化内存管理和改进计算模式,显著提升了模型的性能。实验结果显示,使用FlashAttention2和无填充策略的组合可以将步骤时间减少至323毫秒,相比未优化版本提升了约2.5倍。
42 3
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
|
9天前
|
机器学习/深度学习 算法 PyTorch
基于Pytorch Gemotric在昇腾上实现GraphSage图神经网络
本文详细介绍了如何在昇腾平台上使用PyTorch实现GraphSage算法,在CiteSeer数据集上进行图神经网络的分类训练。内容涵盖GraphSage的创新点、算法原理、网络架构及实战代码分析,通过采样和聚合方法高效处理大规模图数据。实验结果显示,模型在CiteSeer数据集上的分类准确率达到66.5%。
|
5天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
37 1
|
10天前
|
监控 安全 BI
什么是零信任模型?如何实施以保证网络安全?
随着数字化转型,网络边界不断变化,组织需采用新的安全方法。零信任基于“永不信任,永远验证”原则,强调无论内外部,任何用户、设备或网络都不可信任。该模型包括微分段、多因素身份验证、单点登录、最小特权原则、持续监控和审核用户活动、监控设备等核心准则,以实现强大的网络安全态势。
|
2月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于BP神经网络的苦瓜生长含水量预测模型matlab仿真
本项目展示了基于BP神经网络的苦瓜生长含水量预测模型,通过温度(T)、风速(v)、模型厚度(h)等输入特征,预测苦瓜的含水量。采用Matlab2022a开发,核心代码附带中文注释及操作视频。模型利用BP神经网络的非线性映射能力,对试验数据进行训练,实现对未知样本含水量变化规律的预测,为干燥过程的理论研究提供支持。
|
1月前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
90 2
|
1月前
|
运维 网络协议 算法
7 层 OSI 参考模型:详解网络通信的层次结构
7 层 OSI 参考模型:详解网络通信的层次结构
207 1
|
2月前
|
机器学习/深度学习 自然语言处理 监控
利用 PyTorch Lightning 搭建一个文本分类模型
利用 PyTorch Lightning 搭建一个文本分类模型
79 8
利用 PyTorch Lightning 搭建一个文本分类模型
|
2月前
|
网络协议 前端开发 Java
网络协议与IO模型
网络协议与IO模型
146 4
网络协议与IO模型

热门文章

最新文章