十二、Pytorch复现Residual Block

news/2024/5/6 13:42:29/文章来源:https://blog.csdn.net/qq_41264055/article/details/129983218

一、Residual Network

论文出处:Deep Residual Learning for Image Recognition
其核心模块:在这里插入图片描述

二、复现Residual Block

这里以两层卷积层为例进行设计复现
resnet可以很好的解决梯度消失问题
在这里插入图片描述

Residual Block大致要点:
样本x传入模型,分为两个分支,一个分支进行卷积层、relu层、卷积层、relu层;另一个分支中的x不变
最终两个分支通过相加操作结合到一块,最终再relu激活一次即可

1,数据集

老规矩,还使用MNIST手写数字数据集,详情可参考博文:九、多分类问题

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #为了使用relu激活函数
import torch.optim as optim batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),#把图片变成张量形式transforms.Normalize((0.1307,),(0.3081,)) #均值和标准差进行数据标准化,这俩值都是经过整个样本集计算过的
])train_dataset = datasets.MNIST(root='./',train=True,download=True,transform = transform)
train_loader = DataLoader(train_dataset,shuffle=True,batch_size=batch_size)test_dataset = datasets.MNIST(root="./",train=False,download=True,transform=transform)
test_loader = DataLoader(test_dataset,shuffle=False,batch_size=batch_size)

2,测试数据集

这里以训练集中的第1个样本(train_dataset[0])为例进行测试
因为torch中卷积层传入参数格式需要为[B,C,W,H]形式,故通过x.view(-1,1,28,28)进行转换
卷积、relu、卷积、相加、relu
为了保证输入和输出特征大小保持一致,通过加边进行补充

x,y = train_dataset[0]
x.shape
"""
torch.Size([1, 28, 28])
"""
y
"""
5
"""
x = x.view(-1,1,28,28)
x.shape #[B,C,W,H]
"""
torch.Size([1, 1, 28, 28])
"""
channel = x.shape[1] #获取channel#定义Residual Block,无非就是卷积、relu、卷积、relu然后再相加
conv1 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)
conv2 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)conv_1 = conv1(x) #第一次卷积
conv_1.shape
"""
torch.Size([1, 1, 28, 28])
"""
relu_1 = F.relu(conv_1) #relu一下
relu_1.shape
"""
torch.Size([1, 1, 28, 28])
"""H = conv_2 + x
H.shape
"""
torch.Size([1, 1, 28, 28])
"""
final = F.relu(H)
final.shape
"""
torch.Size([1, 1, 28, 28])
"""

3,Residual Block完整模块代码

class y_res(torch.nn.Module):def __init__(self,channel):super(y_res,self).__init__()self.channels = channelself.conv1 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)self.conv2 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)def forward(self,x):conv_1 = self.conv1(x)relu_1 = F.relu(conv_1)conv_2 = self.conv2(relu_1)H = conv_2 + xfinal = F.relu(H)return finalx,y = train_dataset[0]
x = x.view(-1,1,28,28)
channel = x.shape[1]
yy_res = y_res(channel)
final = yy_res(x)
final.shape
"""
torch.Size([1, 1, 28, 28])
"""

三、现学现卖

按照下面的需求进行构建模型
在这里插入图片描述

①准备数据集

数据集使用MNIST手写数字数据集,详细可参考博文:十、CNN卷积神经网络实战

②加载数据集

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #为了使用relu激活函数
import torch.optim as optim batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),#把图片变成张量形式transforms.Normalize((0.1307,),(0.3081,)) #均值和标准差进行数据标准化,这俩值都是经过整个样本集计算过的
])train_dataset = datasets.MNIST(root='./',train=True,download=True,transform = transform)
train_loader = DataLoader(train_dataset,shuffle=True,batch_size=batch_size)test_dataset = datasets.MNIST(root="./",train=False,download=True,transform=transform)
test_loader = DataLoader(test_dataset,shuffle=False,batch_size=batch_size)

③模型构建

残差网络模型架构还是使用上述的模型

class yy_net(torch.nn.Module):def __init__(self):super(yy_net,self).__init__()self.conv1 = torch.nn.Conv2d(1,16,kernel_size=5)self.conv2 = torch.nn.Conv2d(16,32,kernel_size=5)self.maxpool = torch.nn.MaxPool2d(2)self.resblock1 = y_res(16)self.resblock2 = y_res(32)self.linear = torch.nn.Linear(512,10)def forward(self,x):batch_size = x.shape[0] #[B,C,W,H]x = self.maxpool(F.relu(self.conv1(x)))x = self.resblock1(x)x = self.maxpool(F.relu(self.conv2(x)))x = self.resblock2(x)x = x.view(batch_size,-1)x = self.linear(x)return x
class y_res(torch.nn.Module):def __init__(self,channel):super(y_res,self).__init__()self.channels = channelself.conv1 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)self.conv2 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)def forward(self,x):conv_1 = self.conv1(x)relu_1 = F.relu(conv_1)conv_2 = self.conv2(relu_1)H = conv_2 + xfinal = F.relu(H)return final

④损失函数和优化器

lossf = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=0.0001,momentum=0.5)

⑤训练函数构建

def ytrain(epoch):loss_total = 0.0for batch_index ,data in enumerate(train_loader,0):x,y = data#x,y = x.to(device), y.to(device)#GPU加速optimizer.zero_grad()y_hat = model(x)loss = lossf(y_hat,y)loss.backward()optimizer.step()loss_total += loss.item()if batch_index % 300 == 299:# 每300epoch输出一次print("epoch:%d, batch_index:%5d \t loss:%.3f"%(epoch+1, batch_index+1, loss_total/300))loss_total = 0.0 #每次epoch都将损失清除

⑥测试函数构建

def ytest():correct = 0#模型预测正确的数量total = 0#样本总数with torch.no_grad():#测试不需要梯度,减小计算量for data in test_loader:#读取测试样本数据images, labels = data#images, labels = images.to(device), labels.to(device) #GPU加速pred = model(images)#预测,每一个样本占一行,每行有十个值,后续需要求每一行中最大值所对应的下标pred_maxvalue, pred_maxindex = torch.max(pred.data,dim=1)#沿着第一个维度,一行一行来,去找每行中的最大值,返回每行的最大值和所对应下标total += labels.size(0)#labels是一个(N,1)的向量,对应每个样本的正确答案correct += (pred_maxindex == labels).sum().item()#使用预测得到的最大值的索引和正确答案labels进行比较,一致就是1,不一致就是0print("Accuracy on testset :%d %%"%(100*correct / total))#correct预测正确的样本个数 / 样本总数 * 100 = 模型预测正确率

⑦主函数调用

if __name__ == '__main__':for epoch in range(10):#训练10次ytrain(epoch)#训练一次if epoch%10 == 9:ytest()#训练10次,测试1次

⑧完整代码

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #为了使用relu激活函数
import torch.optim as optim batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),#把图片变成张量形式transforms.Normalize((0.1307,),(0.3081,)) #均值和标准差进行数据标准化,这俩值都是经过整个样本集计算过的
])train_dataset = datasets.MNIST(root='./',train=True,download=True,transform = transform)
train_loader = DataLoader(train_dataset,shuffle=True,batch_size=batch_size)test_dataset = datasets.MNIST(root="./",train=False,download=True,transform=transform)
test_loader = DataLoader(test_dataset,shuffle=False,batch_size=batch_size)class yy_net(torch.nn.Module):def __init__(self):super(yy_net,self).__init__()self.conv1 = torch.nn.Conv2d(1,16,kernel_size=5)self.conv2 = torch.nn.Conv2d(16,32,kernel_size=5)self.maxpool = torch.nn.MaxPool2d(2)self.resblock1 = y_res(16)self.resblock2 = y_res(32)self.linear = torch.nn.Linear(512,10)def forward(self,x):batch_size = x.shape[0]x = self.maxpool(F.relu(self.conv1(x)))x = self.resblock1(x)x = self.maxpool(F.relu(self.conv2(x)))x = self.resblock2(x)x = x.view(batch_size,-1)x = self.linear(x)return xclass y_res(torch.nn.Module):def __init__(self,channel):super(y_res,self).__init__()self.channels = channelself.conv1 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)self.conv2 = torch.nn.Conv2d(channel,channel,kernel_size=3,padding=1)def forward(self,x):conv_1 = self.conv1(x)relu_1 = F.relu(conv_1)conv_2 = self.conv2(relu_1)H = conv_2 + xfinal = F.relu(H)return finalmodel = yy_net()     
lossf = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=0.0001,momentum=0.5)   def ytrain(epoch):loss_total = 0.0for batch_index ,data in enumerate(train_loader,0):x,y = data#x,y = x.to(device), y.to(device)#GPU加速optimizer.zero_grad()y_hat = model(x)loss = lossf(y_hat,y)loss.backward()optimizer.step()loss_total += loss.item()if batch_index % 300 == 299:# 每300epoch输出一次print("epoch:%d, batch_index:%5d \t loss:%.3f"%(epoch+1, batch_index+1, loss_total/300))loss_total = 0.0 #每次epoch都将损失清除def ytest():correct = 0#模型预测正确的数量total = 0#样本总数with torch.no_grad():#测试不需要梯度,减小计算量for data in test_loader:#读取测试样本数据images, labels = data#images, labels = images.to(device), labels.to(device) #GPU加速pred = model(images)#预测,每一个样本占一行,每行有十个值,后续需要求每一行中最大值所对应的下标pred_maxvalue, pred_maxindex = torch.max(pred.data,dim=1)#沿着第一个维度,一行一行来,去找每行中的最大值,返回每行的最大值和所对应下标total += labels.size(0)#labels是一个(N,1)的向量,对应每个样本的正确答案correct += (pred_maxindex == labels).sum().item()#使用预测得到的最大值的索引和正确答案labels进行比较,一致就是1,不一致就是0print("Accuracy on testset :%d %%"%(100*correct / total))#correct预测正确的样本个数 / 样本总数 * 100 = 模型预测正确率if __name__ == '__main__':for epoch in range(10):#训练10次ytrain(epoch)#训练一次if epoch%10 == 9:ytest()#训练10次,测试1次

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

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

相关文章

下一个“AI王炸”,别只盯着OpenAI,DeepMind也在憋大招

过去几个月,OpenAI风头无两,各大科技公司争先恐后地跟进大语言模型(LLM)这一技术路线。对比之下,OpenAI的老对手DeepMind,显得有些低调和沉默。微软靠OpenAI打了一场胜仗,而谷歌推出的Bard翻了车…

5.5G,运营商能接受吗?

2月份,我在巴塞罗那参加MWC 2023时有个发现。欧洲通信设备商大多在宣传和讨论6G相关技术,中国通信设备商却在重点展示5.5G,或者叫做5G-Advanced。而全球各国的运营商则都普遍处在比较观望的状态里,两头考察,多样化尝试…

中间表示- 到达定义分析

基本概念 定义(def):对变量的赋值 使用(use):对变量值的读取 问题:能把上图中的y替换为3吗?如果能,这称之为“常量传播”优化。 该问题等价于,有哪些对变量y…

OPNET Modeler 例程——创建一个移动无线网络

文章目录一、例程概述二、创建天线模型三、创建指向处理器四、创建节点模型1.发射机节点模型2.干扰发射机节点模型3.收信机节点模型五、创建网络模型六、收集统计量并运行仿真七、查看仿真结果总结一、例程概述 OPNET 无线模块支持地面和卫星无线系统的构建。在此例程中将构建…

【C++】基础篇

C基础篇什么是C命名空间命名空间的三种使用方式C的输入和输出缺省参数缺省参数分类函数重载引用引用的使用场景常引用指针和引用的区别auto关键字auto使用细则auto不能推导的场景基于范围的for循环范围for的使用条件指针空值nullptr什么是C 1982年,Bjarne Stroustr…

微服务+springcloud+springcloud alibaba学习笔记【Eureka服务注册中心】(3/9)

Eureka服务注册中心 3/91、服务注册与发现1.1 什么是服务治理:1.2 什么是服务注册与发现:1.3 Eureka服务注册与发现2、单机版eureka2.1 创建module2.2改pom依赖2.3写yml配置文件:2.4主启动类2.5 修改服务提供者 cloud-provider-payment8001 模块&#xf…

GFS的卷类型与集群实验文档

GlusterFS 支持七种卷,即分布式卷、条带卷、复制卷、分布式条带卷、分布式复制卷、条带复制卷和分布式条带复制卷。我们常用的有前五种,今天我们就来看一看这五种卷都有什么优缺点。 一、分布式卷(Distribute volume) 文件通过 H…

【模型复现】resnet,使用net.add_module()的方法构建模型。小小的改进大大的影响,何大神思路很奇妙,基础很扎实

从经验来看,网络的深度对模型的性能至关重要,当增加网络层数后,网络可以进行更加复杂的特征模式的提取,所以当模型更深时理论上可以取得更好的结果。但是更深的网络其性能一定会更好吗?实验发现深度网络出现了退化问题…

python玄阶斗技--tkinter事件

在前一篇文章中,我们已经了解是tkinter的一些标签的使用,但一个GUI程序除了让别人看到,还要有一些交互操作,实现人机交互的方法我们称为事件,通过事件分为:鼠标事件,键盘事件和窗口事件。接下来…

Neo4j初学者使用记录(在更)

打开Neo4j cmdR 输入neo4j console 浏览器中输入框中网址:http://localhost:7474/即可打开 新建库 服务器版需要更改配置文件,若neo4j服务正在运行,则按Ctrlc,停止该服务。 配置完后,再重新开启服务,刷新…

如何利用ventoy制作Linux to go (把deepin放到U盘里)

准备工作 最新版本 – 深度科技社区 (deepin.org) deepin镜像官方下载即可 Releases ventoy/vtoyboot GitHub ventoy启动插件选择1.0.29版本 Downloads – Oracle VM VirtualBox VirtualBox虚拟机官网 ventoy下载 VentoyRelease (lanzoui.com) 选择下载1.0.29版本 vento…

第五十八章 线段树(一)

第五十八章 线段树(一)一、树状数组的缺陷二、线段树的作用三、线段树的基本构成1、节点定义2、线段树的结构四、线段树的重要函数1、构造线段树——bulid函数2、查询区间——query函数3、单点修改——modify函数五、例题一、树状数组的缺陷 在前面两个…

对于电商行业来讲,真正决定它的并不是规模,而是载体

纵然是在现在这样的情况之下,我们依然无法用「格局已定」来形容和阐述现在的电商市场格局。这一点,我们可以从以抖音、快手为代表的电商新势力的崛起当中,看出一丝端倪。对于电商行业来讲,真正决定它的并不是规模,而是…

Dart中的异步

一 事件循环 flutter 就是运行在一个root isolate 中 程序只要运行起来,就有一个事件循环一直在运行 ,直至程序退出。 EventLoop 先从mrcro 对列中取任务,取完任务再去 event 队列中取任务。队列任务是FIFO。 二 认识Future abstract clas…

[JavaEE]----Spring03

文章目录Spring_day031,AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念2,AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知…

C++内存管理(new和delete)

目录 1. new/delete操作内置类型 2. new和delete操作自定义类型 3. operator new与operator delete函数 4 .new和delete的实现原理 1 .内置类型 2 .自定义类型 new的原理 delete的原理 new T[N]的原理 delete[]的原理 5. 定位new表达式(placement-new) 6. malloc/f…

使用Process Explorer和Clumsy定位软件高CPU占用问题

目录 1、问题描述 2、使用Process Explorer初步找到CPU占用高的原因 3、使用Clumsy工具在公司内网环境复现了问题 4、根据Process Explorer中的函数调用堆栈,分析源码,最终找出了问题 5、总结 在排查项目客户的视频图像闪烁问题时,无意中…

Centos7安装部署Jenkins

Jenkins简介: Jenkins只是一个平台,真正运作的都是插件。这就是jenkins流行的原因,因为jenkins什么插件都有 Hudson是Jenkins的前身,是基于Java开发的一种持续集成工具,用于监控程序重复的工作,Hudson后来被…

JavaScript基础-02

常量(字面量):数字和字符串 常量也称之为“字面量”,是固定值,不可改变。看见什么,它就是什么。 常量有下面这几种: 数字常量(数值常量)字符串常量布尔常量自定义常量…

【MATLAB数学建模编程实战】Kmeans算法编程及算法的简单原理

欢迎关注,本专栏主要更新MATLAB仿真、界面、基础编程、画图、算法、矩阵处理等操作,拥有丰富的实例练习代码,欢迎订阅该专栏!(等该专栏建设成熟后将开始收费,快快上车吧~~) 【MATLAB数学建模编…