6.6 实现卷积神经网络LeNet训练并预测手写体数字

模型架构

在这里插入图片描述
在这里插入图片描述

代码实现

import torch
from torch import nn
from d2l import torch as d2l
net = nn.Sequential(nn.Conv2d(1,6,kernel_size=5,padding=2),nn.Sigmoid(),#padding=2补偿5x5卷积核导致的特征减少。nn.AvgPool2d(kernel_size=2,stride=2),nn.Conv2d(6,16,kernel_size=5),nn.Sigmoid(),nn.AvgPool2d(kernel_size=2,stride=2),nn.Flatten(),nn.Linear(16*5*5,120),nn.Sigmoid(),nn.Linear(120,84),nn.Sigmoid(),nn.Linear(84,10)
)
'''定义X,并打印模型的形状'''
# 第一个参数是样本
X = torch.rand(size=(1,1,28,28),dtype=torch.float32)
for layer in net:X = layer(X)print(layer.__class__.__name__,'output shape: \t',X.shape)
# 输出如下:
Conv2d output shape: 	 torch.Size([1, 6, 28, 28])
Sigmoid output shape: 	 torch.Size([1, 6, 28, 28])
AvgPool2d output shape: 	 torch.Size([1, 6, 14, 14])
Conv2d output shape: 	 torch.Size([1, 16, 10, 10])
Sigmoid output shape: 	 torch.Size([1, 16, 10, 10])
AvgPool2d output shape: 	 torch.Size([1, 16, 5, 5])
Flatten output shape: 	 torch.Size([1, 400])
Linear output shape: 	 torch.Size([1, 120])
Sigmoid output shape: 	 torch.Size([1, 120])
Linear output shape: 	 torch.Size([1, 84])
Sigmoid output shape: 	 torch.Size([1, 84])
Linear output shape: 	 torch.Size([1, 10])
'''定义训练批次并加载训练集和测试集'''
batch_size = 256
# 按照batch_size把数据集取出来。取出来之后是放到内存中的,后面要把它加载到GPU中
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)
# 计算预测正确的个数
def accuracy(y_hat,y):'''计算预测正确的数量'''if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:# y_hat是下标表示类别,值是该类别的概率。模型结果是预测10个类的概率,谁的概率最大,就取谁的下标y_hat = y_hat.argmax(axis=1)#  y_hat.type(y.dtype):因为==对数据类型很敏感,因此我们将y_hat的数据类型转换为与y的数据类型一致。#  y_hat.type(y.dtype) == y,将预测值y_hat与真实值y比较,返回一个包含 0和1的张量,赋值给cam,最后求和会得到正确预测的数量。cam = y_hat.type(y.dtype) == yreturn float(cam.type(y.dtype).sum())
def evaluate_accuracy_gpu(net,data_iter,device=None):if isinstance(net,nn.Module):net.eval() # 将模型设置为评估模式if not device:'''iter(net.parameters())是将参数集合转换为迭代器,并获取其中的第一个元素next(iter(net.parameters())).device ,指取到net.parameters()的第一个元素,获取该元素的设备。'''device = next(iter(net.parameters())).device# Accumulator用于对多个变量进行累加,d2l.Accumulator(2) 是在Accumulator实例中创建了2个变量,分别用于存储正确预测的数量和预测的总数量。当我们遍历数据集时,两者都随着时间的推移而累加。metric = d2l.Accumulator(2) # 正确预测数,预测总数with torch.no_grad():for X,y in data_iter:if isinstance(X,list): # 详见文章最下面的补充内容X = [x.to(device) for x in X] # 令X使用设备deviceelse:X = X.to(device)y = y.to(device)# y.numel()是批次中样本的数量,accuracy(net(X),y)是用于计算模型在输入数据X上的输出结果与标签Y之间的准确率。# metric.add函数将正确预测的数量 和 样本数量作为参数传递进去,用于记录和累计这些指标的值。metric.add(accuracy(net(X),y),y.numel())return metric[0]/metric[1] # 返回准确率,其中metric[0]存放的是正确预测的个数,metric[1]存放的是样本数量,
def train_ch6(net,train_iter,test_iter,num_epochs,lr,device):def init_weights(m):if type(m) == nn.Linear or type(m) == nn.Conv2d: # 对神经网络中的线性层和卷积层的权重进行初始化nn.init.xavier_uniform_(m.weight) #用于初始化权重的函数,net.apply(init_weights)print('training on',device)net.to(device) # 设置模型使用deviceoptimizer = torch.optim.SGD(net.parameters(),lr=lr)loss = nn.CrossEntropyLoss()'''该代码创建了一个名为animator的动画器,用于在训练过程中可视化损失函数和准确率的变化情况'''animator = d2l.Animator(xlabel='epoch',xlim=[1,num_epochs],legend=['train loss','train acc','test acc'])timer,num_batches = d2l.Timer(),len(train_iter)for epoch in range(num_epochs):# 创建 Accumulator类,统计训练损失之和,正确预测个数之和,样本数metric = d2l.Accumulator(3)net.train()for i,(X,y) in enumerate(train_iter):timer.start()optimizer.zero_grad()X,y = X.to(device),y.to(device)y_hat = net(X)l = loss(y_hat,y)l.backward()optimizer.step()with torch.no_grad():metric.add(l*X.shape[0], d2l.accuracy(y_hat,y), X.shape[0])timer.stop()train_l = metric[0] / metric[2] # 损失之和 / 样本数train_acc = metric[1] / metric[2] # 正确预测个数 / 样本数if (i+1) % (num_batches//5)==0 or i == num_epochs-1:animator.add(epoch + (i+1)/num_epochs,(train_l,train_acc,None))test_acc = evaluate_accuracy_gpu(net,test_iter)animator.add(epoch+1,(None,None,test_acc))print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, 'f'test acc {test_acc:.3f}')print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec 'f'on {str(device)}')
# 定义学习率和批次 开始训练
lr,num_epochs = 0.9,10
train_ch6(net,train_iter,test_iter,num_epochs,lr,d2l.try_gpu())

在这里插入图片描述

练习

把平均汇聚层改为最大汇聚层

在这里插入图片描述

把平均池化改为最大池和把激活函数改为RelU之后的效果

net = nn.Sequential(nn.Conv2d(1,6,kernel_size=5,padding=2),nn.ReLU(),#padding=2补偿5x5卷积核导致的特征减少。nn.MaxPool2d(kernel_size=2,stride=2),nn.Conv2d(6,16,kernel_size=5),nn.ReLU(),nn.MaxPool2d(kernel_size=2,stride=2),nn.Flatten(),nn.Linear(16*5*5,120),nn.ReLU(),nn.Linear(120,84),nn.Sigmoid(), #注意,此处不能改为RelU,此处的sigmoid是把预测结果映射成概率nn.Linear(84,10)
)

在这里插入图片描述

使用训练好的模型进行预测

y_hat = net(x)

补充:

isinstance(net,nn.Module)

isinstance(net,nn.Module)是Python的内置函数,用于判断一个对象是否属于制定类或其子类的实例。如果net是nn.Module类或子类的实例,那么表达式返回True,否则返回False. nn.Module是pytorch中用于构建神经网络模型的基类,其他神经网络都会继承它,因此使用 isinstance(net,nn.Module),可以确定Net对象是否为一个有效的神经网络模型。

`nn.init.xavier_uniform_(m.weight)

nn.init.xavier_uniform_(m.weight) 是一个用于初始化权重的函数,采用的是 Xavier 均匀分布初始化方法。

在神经网络中,权重的初始化非常重要,合适的初始化可以帮助网络更好地学习和收敛。Xavier 初始化方法是一种常用的权重初始化方法之一,旨在使权重在前向传播过程中保持方差不变。

具体而言,nn.init.xavier_uniform_() 函数会对输入的权重张量 m.weight 进行操作,将其初始化为一个均匀分布中的随机值。这个均匀分布的范围根据权重张量的形状进行调整,以保持前向传播过程中特征的方差稳定。

通过使用 Xavier 初始化方法,可以加速神经网络的训练过程,并且有助于避免梯度消失或梯度爆炸等问题。

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

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

相关文章

Node.js-npm包管理工具的介绍

一、概念 包,代表一组特定功能的源码集合。 包管理工具,管理包的应用软件,可以下载安装、更新、删除包等操作,在项目开发中大大提高开发效率。 npm全称:Node Package Manager 二、npm使用 如果安装了 node,…

OpenStreetMap数据转3D场景【Python + PostgreSQL】

很长一段时间以来,我对 GIS 和渲染感兴趣,在分别尝试这两者之后,我决定最终尝试以 3D 方式渲染 OpenStreetMap 中的地理数据,重点关注不超过城市的小规模。 在本文中,我将介绍从建筑形状生成三角形网格、以适合 Blend…

iperf3-性能测试

iperf3-性能测试 安装1.apt安装2.源码安装 使用方法iperf原理测试参考文档性能测试客户端服务端 官方文档:https://iperf.fr/iperf-doc.php 安装 1.apt安装 sudo apt-get install iperf32.源码安装 # 按照官方说明安装 ./configure make sudo make install执行编…

node中使用express+mongodb实现分页查询

文章目录 引言一、分页案例二、查询方法扩展介绍1. find()2. limit()3. skip()4. populate() 总结 引言 在Web应用程序开发中,分页查询是必不可少的功能之一。Node.js提供了许多优秀的工具和框架来实现分页查询,其中最流行的框架之一就是Express。同时&…

8.2一日总结

1.记录更新: untracked: 未追踪(新增的文件) unmodefied: 未修改 modefied: 已修改 staged: 已暂存 2、添加指定文件到暂存区: git add 文件名 gi…

docker 怎么搭建

Docker是一种容器化平台,可以快速构建、部署和运行应用程序。以下是Docker的搭建流程: 1. 安装Docker 在官方网站上下载并安装Docker,根据官方指引进行安装。 2. 配置Docker环境: 配置Docker环…

GATK ApplyBQSRSpark 过程中因No space left on device终止

Error: GATK ApplyBQSRSpark 过程中因No space left on device终止 执行命令: nohup time ./gatk --java-options "-Xmx128G" ApplyBQSRSpark --spark-master local[20] -R ../../alignment/hg38/hg38.fa -I ../../alignment/bam/P368T.s…

微信小程序nodejs+vue+uniapp高校食堂线上预约点餐系统

本次设计任务是要设计一个食堂线上预约点餐系统,通过这个系统能够满足管理员及学生的食堂线上预约点餐分享功能。系统的主要包括首页、个人中心、学生管理、菜品分类管理、菜品管理、关于我们管理、意见反馈、系统管理、订单管理等功能。 开发语言 node.js 框架&am…

【论文阅读】对抗溯源图主机入侵检测系统的模仿攻击(NDSS-2023)

作者:伊利诺伊大学芝加哥分校-Akul Goyal、Gang Wang、Adam Bates;维克森林大学-Xueyuan Han、 引用:Goyal A, Han X, Wang G, et al. Sometimes, You Aren’t What You Do: Mimicry Attacks against Provenance Graph Host Intrusion Detect…

BenchmarkSQL 支持 TiDB 驱动以及 tidb-loadbalance

作者: GangShen 原文来源: https://tidb.net/blog/3c274180 使用 BenchmarkSQL 对 TiDB 进行 TPC-C 测试 众所周知 TiDB 是一个兼容 MySQL 协议的分布式关系型数据库,用户可以使用 MySQL 的驱动以及连接方式连接 TiDB 进行使用&#xff0…

Git从远程仓库中删除文件,并上传新文件

目录 删除: 拉取远程分支的更新: ​编辑 首先查看git状态: ​编辑 删除文件并提交版本库: 提交: 上传新文件: 首先查看git状态: 提交到暂存区: 提交到版本库: 上…

基于Spring Boot的在线视频教育培训网站设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频: 基于Spring Boot的在线视频教育培训网站设计与实现(Javaspring bootMySQL) 使用技术: 前端:html css javascript jQuery ajax thymeleaf 微信小程序 后端:Java sp…

Python插件PyAutoGui的使用方法

Python插件PyAutoGui的使用方法 一、控制鼠标二、图片处理三、控制键盘四、其他方法 一、控制鼠标 pyautogui.moveTo(w - 100, h - 100, duration0.25) # 立即移动到指定x, y位置坐标, duration表示移动花费的时间,0表示立即 pyautogui.moveRel(100, 0…

skywalking日志收集

文章目录 一、介绍二、添加依赖三、修改日志配置1. 添加链路表示traceId2. 添加链路上下文3. 异步日志 四、收集链路日志 一、介绍 在上一篇文章skywalking全链路追踪中我们介绍了在微服务项目中使用skywalking进行服务调用链路的追踪。 本文在全链路追踪的基础上&#xff0c…

没有fastjson,rust怎么方便的解析提取复杂json呢?

在 Rust 中解析和提取复杂的 JSON 结构,你可以使用 serde_json 库来处理。 serde_json 提供了一组功能强大的方法来解析和操作 JSON 数据。 下面是一个示例,展示了如何解析和提取复杂的 JSON 结构: use serde_json::{Value, Result}; fn mai…

gradle项目Connection timed out,build时先下载gradle问题download gradle-x.x-bin.zip

IDEA 导入 Gradle 项目,编译的时候会默认下载 配置版本的Gradle.zip问题,一般会下载失败,提示Connection timed out,连接超时。 解决办法: 修改项目根目录下gradle目录下的gradle-wrapper.properties文件,…

探索 Go 语言中 iota 的神奇力量,优雅定义常量!

大家好!在今天的文章中,我将为大家介绍一下关于 golang 中的 iota 的使用技巧和注意事项。作为一种枚举常量生成器,iota 在 golang 中被广泛使用,可以简化代码和提高可读性。下面就让我们来了解一些关键的使用技巧和注意事项吧&am…

前端开发中如何进行多主题配置

在前端开发中实现多主题配置可以让用户根据个人喜好或者场景需求选择不同的界面风格! 下面来为大家一一介绍实现切换主题配置的方法! 1、CSS 变量 使用CSS变量来定义主题相关的颜色、字体、间距等属性,然后在不同主题下修改这些变量的值。…

【操作系统】进程和线程对照解释

进程(Process)和线程(Thread)都是操作系统中用于执行任务的基本单位,但它们有着不同的特点和使用方式。 进程(Process): 进程是正在运行的程序的实例。一个程序在运行时会被操作系统…

LLM as Co-pilot:AutoDev 1.0 发布,开源全流程 AI 辅助编程

四月,在那篇《AutoDev:AI 突破研发效能,探索平台工程新机遇》,我们初步拟定了 AI 对于研发的影响。我们有了几个基本的假设: 中大型企业将至少拥有一个私有化的大语言模型。只有构建端到端工具才能借助 AI 实现增质提效…