LeNet-5上手敲代码

LeNet-5

LeNet-5Yann LeCun在1998年提出,旨在解决手写数字识别问题,被认为是卷积神经网络的开创性工作之一。该网络是第一个被广泛应用于数字图像识别的神经网络之一,也是深度学习领域的里程碑之一。

LeNet-5的整体架构:

在这里插入图片描述

总体来看LeNet-5由两个部分组成:

  • 卷积编码器:由两个卷积层和两个下采样层组成;
  • 全连接层密集块:由三个全连接层组成

特点:

1.相比MLPLeNet使用了相对更少的参数,获得了更好的结果。

2.设计了MaxPool来提取特征

代码实现

1. 模型文件的实现

通过观察模型的整体架构,可以知到LeNet-5只用了三个基本的层——卷积层、下采样层、全连接层,因此我们很容易写出模型的基本框架。

其中Gaussian connections也是一个全连接层。Gaussian Connections利用的是RBF函数(径向欧式距离函数),计算输入向量和参数向量之间的欧式距离。目前该方式基本已淘汰,取而代之的是Softmax

为了提高模型的性能,我们会在卷积层与下采样层之间添加一个Relu激活函数,因此模型的整体流程架构为:

Convolutions -> Relu->Subsampling -> Convolutions -> Relu-> Subsampling -> Full connection -> Full connection -> Full connection

pytorch中,卷积层对应的是nn.Conv2d()方法, 下采样层可以使用pytorch中的最大池化下采样nn.MaxPool2d()方法来实现,全连接层可以使用nn.Linear()方法来实现。

确定参数:

卷积层:对于LeNet-5论文中输入的图片是 32 × 32 32 \times 32 32×32大小的图片(图片通道个数为3)。因此第一个卷积层的输入的通道个数为3,输出的通道个数为16,也就是说一共有16个卷积核。卷积核的个数等于通过卷积后图片的通道个数

我们可以根据如下公式来计算出卷积核的大小。

计算卷积后图像宽和高的公式

  • I n p u t : ( N , C i n , H i n , W i n ) Input:(N, C_{in},H_{in},W_{in}) Input(NCinHinWin)

  • O u t p u t : ( N , C o u t , H o u t , W o u t ) Output:(N,C_{out},H_{out},W_{out}) Output(NCoutHoutWout)

H o u t = [ H i n + 2 × p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] × ( k e r n e l _ s i z e [ 0 ] − 1 ) − 1 s t r i d e [ 0 ] + 1 ] H_{out} = [\frac{H_{in} + 2 \times padding[0] - dilation[0] \times (kernel\_size[0] - 1) - 1}{stride[0]} + 1] Hout=[stride[0]Hin+2×padding[0]dilation[0]×(kernel_size[0]1)1+1]

W o u t = [ W i n + 2 × p a d d i n g [ 1 ] − d i l a t i o n [ 1 ] × ( k e r n e l _ s i z e [ 1 ] − 1 ) − 1 s t r i d e [ 1 ] + 1 ] W_{out} = [\frac{W_{in} + 2 \times padding[1] - dilation[1] \times (kernel\_size[1] - 1) - 1}{stride[1]} + 1] Wout=[stride[1]Win+2×padding[1]dilation[1]×(kernel_size[1]1)1+1]

公式中dilation我们没有使用,默认情况为1,输入的图片为 32 × 32 × 3 32 \times 32 \times 3 32×32×3输出为 28 × 28 × 6 28 \times 28 \times 6 28×28×6,通过公式,我们很容易算出 k e r n e l s i z e = ( 5 , 5 ) kernel_{size} = (5, 5) kernelsize=(5,5)【通常情况下如果通过卷积层后的图片的大小没有很明显的缩小(成倍数缩小),那么stride一般为默认值1,通过以上公式,我们可以求得每一个卷积核的大小 。

最大池化下采样:由于特征图通过最大池化下采样层之后,图片的大小变为原来的一半,因此我们知道在长度方向上每两个像素之间取一个最大值,这样才能将长度变为原来的一半,宽度方向上每两个像素之间取一个最大值,这样才能将宽度变为原来的一半。结合起来得到池化层的每一个滑动窗口的大小为 2 × 2 2 \times 2 2×2,也就是说,每四个像素取一个最大值。

在这里插入图片描述

全连接层:输入为上一个层的输出数据大小,输出为自定义大小,对于第一个全连接层,输入为下采样层的输出,即: 5 × 5 × 16 5 \times 5 \times 16 5×5×16 个矩阵值。输出为下一个全连接层单元的个数(第二个全连接层的单元个数为84个),可以推出所有全连接层的单元个数。

model.py

import torch
import torch.nn as nn
import torch.nn.functional as Fclass LeNet(nn.Module):def __init__(self):super(LeNet, self).__init__()self.conv1 = nn.Conv2d(3, 6, (5, 5))self.pool1 = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, (5, 5))self.pool2 = nn.MaxPool2d(2, 2)self.fc1 = nn.Linear(16 * 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))x = self.pool1(x)x = F.relu(self.conv2(x))x = self.pool2(x)x = x.view(-1, 16 * 5 * 5)   # 改变张量形状为一个二维张量,第一个维度是自动推断的,第二个维度设定为16 * 5 * 5x = self.fc1(x)x = self.fc2(x)x = self.fc3(x)return xif __name__ == '__main__':model =  LeNet()x = torch.randn((3, 32, 32))output = model(x)print(x)

2. 训练程序

写训练程序的基本步骤为:

  1. 加载训练数据
  2. 初始化模型
  3. 设定损失函数
  4. 设定优化器
  5. 设定迭代次数
  6. 根据情况保存模型权重文件

训练数据我们使用的是CIFAR10中的训练数据,验证集的数据也使用的是CIFAR10中的数据,同时将训练集和验证集的数据进行转换(转换为tensor类型,进行归一化)。设置dataloader,训练集的batch_size64,并且进行随机打乱,设置num_workers2,验证集的batch_size5000,进行随机打乱,设置num_workers2

num_workers:用于设置是否使用多线程读取数据,开启后会加快数据读取速度,但是会占用更多内存,内存较小的电脑可以设置为2或者0

训练数据时,我们在每次的500步之后进行一次验证,验证的方式为,加载验证集,然后输入到网络中进行预测,得到输出的最大值的索引,然后再与真实标签进行比较,统计为True的个数,然后除以所有的标签的个数,得到最后的模型的正确率。

predict_y = torch.max(outputs, dim=1)[1]
accuracy = torch.eq(predict_y, test_label).sum().item() / test_label.size(0)  # .item() 方法将结果转换为标量,即 Python 中的普通数字类型。

在迭代完所有的步数之后进行保存模型的权重文件。

train.py

import torch
import torchvision
from torch import nn, optim
from torch.utils.data import DataLoaderfrom model import LeNetdef main():device = torch.device("cuda" if torch.cuda.is_available() else "cpu")transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor(), torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 训练集train_set = torchvision.datasets.CIFAR10(root="./data", train=True, download=False, transform=transform)train_loader = DataLoader(dataset=train_set, batch_size=64, shuffle=True, num_workers=2)# 验证集test_set = torchvision.datasets.CIFAR10(root='./data', train=False, download=False, transform=transform)test_loader = DataLoader(dataset=test_set, batch_size=5000, shuffle=True, num_workers=0)# 实例化网络,损失函数,优化器net = LeNet().to(device)net.load_state_dict(torch.load('LeNet_200.pth'))  # 加载权重loss_function = nn.CrossEntropyLoss().to(device)optimizer = optim.Adam(net.parameters(), lr=0.001)epochs = 200epoch = 0# 开始训练print("training...")while epoch <= epochs:epoch += 1running_loss = 0.0for step, data in enumerate(train_loader):print(f"epoc: {epoch}, step: {step}")inputs, lables = datainputs, lables = inputs.to(device), lables.to(device)   # 将数据移动到GPU上optimizer.zero_grad()output = net(inputs)loss = loss_function(output, lables)loss.backward()optimizer.step()running_loss += loss.item()if step % 500 == 499:   # 每500个batch_size之后进行验证一次with torch.no_grad():test_image, test_label = next(iter(test_loader))  # iter(test_loader)作用是设定一个迭代器,这行代码的作用是取出验证集中的一个batch_size的图片和对应的标签。test_image, test_label = test_image.to(device), test_label.to(device)  # 将数据移动到 GPU 上outputs = net(test_image)predict_y = torch.max(outputs, dim=1)[1]accuracy = torch.eq(predict_y, test_label).sum().item() / test_label.size(0)  # .item() 方法将结果转换为标量,即 Python 中的普通数字类型。print('[%d, %5d] train_loss: %.3f  test_accuracy: %.3f' %(epoch + 1, step + 1, running_loss / 500, accuracy))running_loss = 0.0print(f"The epoc is {epoch}")print("Finish Training")save_path = "./LeNet.pth"torch.save(net.state_dict(), save_path)if __name__ == '__main__':main()

3. 验证程序

验证程序,首先需要加载图片,然后进行转换(包括裁剪为模型的输入形状大小【这里为 32 × 32 32 \times 32 32×32】,然后转换为tensor类型,最后进行归一化),将预处理后的图片送入到模型中,模型输出的是一个batch_size个一维向量,每一个一维向量有10个数,表示输出的类别一共有10个,取10个中值最大的数的索引作为预测的类别,可以使用以下代码:predict = torch.max(outputs, dim=1)[1].numpy(),这表示在模型输出的结果中,取第一个维度上的10个数取最大值的索引,并将其转换为numpy类型的数据。然后将这个数对照标签的映射关系,可以得到最终预测的类别。

varify.py

import torch
import torchvision.transforms as transforms
from PIL import Imagefrom model import LeNetdef main():transform = transforms.Compose([transforms.Resize((32, 32)),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')net = LeNet()net.load_state_dict(torch.load('LeNet_250.pth'))im = Image.open('2.jpg')  # 加载图片im = transform(im)  # [C, H, W]im = torch.unsqueeze(im, dim=0)  # [N, C, H, W]with torch.no_grad():  # 用于设置在该上下文中不进行梯度计算,因为推断时不需要计算梯度,可以提高计算效率。outputs = net(im)predict = torch.max(outputs, dim=1)[1].numpy()print(classes[int(predict)])if __name__ == '__main__':main()

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

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

相关文章

免费思维13招之四:主副型思维

免费思维13招之四:主副型思维 本节,给你分享一下产品型思维的第二种子思维:主副型思维 什么是主副型思维呢?传统的主副型思维是指对企业的核心、利润最高的产品进行收费,一些附加品、延伸产品进行让利,赠送给客户。 但是这早已过时了,现在升级之后的产品型思维,就是将…

VisualGDB:Linux静态库项目创建、编译及库的使用

接上篇《VisualGDB&#xff1a;Linux动态库项目创建、编译及库的使用》&#xff0c;静态库的创建和使用与动态库基本无差别&#xff0c;唯一需要做的就是指定项目生成静态库。 一、指定项目生成静态库 二、重新构建和编译项目 这里注意&#xff0c;同样要copy一个libxxx.so格式…

Linux 无名信号量(Semaphore)的使用

目录 一、无名信号量的概念二、无名信号量相关函数三、信号量的使用步骤四、应用场景五、测试代码 一、无名信号量的概念 Linux无名信号量&#xff08;Semaphore&#xff09;   在Linux操作系统中&#xff0c;信号量&#xff08;Semaphore&#xff09;是一种用于进程间或线程…

内网穿透速度慢

内网穿透速度慢原因及优化策略 在计算机网络应用中&#xff0c;内网穿透是一个常见的需求&#xff0c;它允许外部网络访问位于内部网络&#xff08;如企业局域网或家庭网络&#xff09;中的设备或服务。然而&#xff0c;有时用户在进行内网穿透时会遇到速度慢的问题&#xff0…

AI视频教程下载:给企业管理层和商业精英的ChatGpt课程

课程内容大纲&#xff1a; 1-引言 2-面向初学者的生成性人工智能 3-与ChatGPT一起学习提示101 详细介绍了如何使用ChatGPT的六种沟通模式&#xff0c;并提供了各种实际应用场景和示例&#xff1a; **Q&A模式&#xff08;问题与答案模式&#xff09;**&#xff1a; - 这…

打印机处于脱机状态如何恢复到正常状态?最简单!

当打印机一直处于脱机状态但打印机重启了好几遍仍然无效果时&#xff0c;尝试以下方法或许会成功&#xff01; 1.打开设置&#xff0c;在主页界面会有它的推荐设置&#xff0c;如上图&#xff0c;此时只需要点击“打印机和扫描仪”这个方框即可 2.但也并不是每次都会有推荐设置…

从零开始!学习绘制3D表情的详细指南

在2020 年的苹果全球开发者大会(WWDC)&#xff0c;苹果发布了新的 macOS 11(又名 Big Sur)。其中在UI视觉方面macOS Big Sur 系统最大的变化就是图标上&#xff0c; Big Sur更新了很多新设计风格的 3D应用图标&#xff0c;3D设计的确可以提升UI整体的视觉氛围&#xff0c;并且现…

wsl2安装rancher并导入和创建k8s集群

环境准备 安装wsl2点击此文]ubuntu20.04安装docker 点击此文,安装完成后docker镜像仓库改成阿里云镜像加速地址.如果不熟请点击此文 docker 安装rancher 启动wsl,根据官方文档以root身份执行 sudo docker run -d --restartunless-stopped -p 80:80 -p 443:443 --privileged …

《基于GNU-Radio和USRP的雷达通信系统的实现》文献阅读

文章目录 前言一、摘要二、引言三、联合系统实施1、基本原理2、实验方案 四、软件设置1、发射机2、接收机 五、实验结果1、实验设置2、波形3、室内外对比4、不同参数的结果 六、结论七、参考文献八、论文自取九、阅读收获 前言 本文记录《基于GNU-Radio和USRP的雷达通信系统的实…

2024粤港澳青少年信息学创新大赛C++知识点汇总和真题训练

2024粤港澳青少年信息学创新大赛C知识点汇总和真题训练 知识汇总 真题训练 程序设计语言C是一种解释性语言。 A.正确 B.错误 Python是一种编译型语言。 A.正确 B.错误 误 RAM&#xff08;随机存取存储器&#xff09;是一种易失性存储设备。 A.正确 B.错误 Java…

Docker-harbor

一、搭建本地私有仓库 1.1 下载Registry镜像 1.2 添加本地私有仓库配置 1.3 重启服务并运行Registry容器 1.4.容器的操作 1.4.1 拉取Nginx镜像并为镜像打标签 1.4.2 上传到私有仓库 1.4.3 列出私有仓库所有镜像 1.4.4 列出私有仓库的镜像的所有标签 1.4.5 先删除原有…

基于鸢尾花数据集实施自组织神经网络聚类分析

基于鸢尾花数据集实施自组织神经网络聚类分析 1. 自组织神经网络的基础知识2. 鸢尾花数据集的自组织分类3. SOM的无监督聚类 1. 自组织神经网络的基础知识 自组织神经网络也称自组织映射&#xff08;SOM&#xff09;或自组织特征映射&#xff08;SOFM&#xff09;&#xff0c;…

Coze扣子开发指南:用免费API自己创建插件

虽然Coze扣子现在插件商店已经有几百个插件了&#xff0c;但相对于海量人群的众多差异化需求&#xff0c;还是远远不够的。如果插件商店没有合适的插件&#xff0c;其实完成可以自己创建&#xff0c;过程也很简单&#xff0c;不需要编写任何代码。 首先打开个人空间&#xff0…

AcWing 835:Trie字符串统计 ← 字典树(Trie树)模板题

【题目来源】https://www.acwing.com/problem/content/837/【题目描述】 维护一个字符串集合&#xff0c;支持两种操作&#xff1a; ● I x 向集合中插入一个字符串 x&#xff1b; ● Q x 询问一个字符串在集合中出现了多少次。 共有 N 个操作&#xff0c;所有输入的字符…

Linux sudo 指令

sudo命令 概念&#xff1a; sudo是linux下常用的允许普通用户使用超级用户权限的工具&#xff0c;允许系统管理员让普通用户执行一些或者全部的root命令&#xff0c;如halt&#xff0c;reboot&#xff0c;su等。这样不仅减少了root用户的登录和管理时间&#xff0c;同样也提高…

22、Flink 背压下的 Checkpoint处理

1.概述 通常&#xff0c;对齐 Checkpoint 的时长主要受 Checkpointing 过程中的同步和异步两个部分的影响&#xff1b;但当 Flink 作业正运行在严重的背压下时&#xff0c;Checkpoint 端到端延迟的主要影响因子将会是传递 Checkpoint Barrier 到 所有的算子/子任务的时间&…

线程与进程

进程 进程是程序的一次执行过程&#xff0c;系统程序的基本单位。有自己的main方法&#xff0c;并且主要由主方法运行起来的基本上就是进程。 线程 线程与进程相似&#xff0c;但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是…

局域网语音对讲系统_IP广播对讲系统停车场解决方案

局域网语音对讲系统_IP广播对讲系统停车场解决方案 需求分析&#xff1a; 随着国民经济和社会的发展&#xff0c; 选择坐车出行的民众越来越多。在保护交通安全的同时&#xff0c;也给停车场服务部门提出了更高的要求。人们对停车场系统提出了更高的要求与挑战&#xff0c; 需要…

部分设计模式概述

单例模式 工厂模式 适配器模式 模板方法模式 策略模式 责任链 观察者模式&#xff08;又叫发布订阅模式&#xff09;

容器化Jenkins远程发布java应用(方式一:pipline+ssh)

1.创建pipline工程 2.准备工程Jenkinsfile文件&#xff08;java目录&#xff09; 1.文件脚本内容 env.fileName "planetflix-app.jar" env.configName "planetflix_prod" env.remoteDirectory "/data/project/java" env.sourceFile "/…