简单复现 残差网络、Googlenet、mobilenet、SqueezeNet、ShuffleNet

news2024/11/26 7:42:15

1.残差网络

1)网络结构

当对x求偏导的时候,F(x)对x求偏导的值很小的时候,对整体求x的偏导会接近于1

这样解决了梯度消失问题,我们可以对离输入很近的层进行很好的更新。

要注意的是F(x)与x的张量维度是相同的。

2)代码 

import torch
from torchvision import transforms   #对图像做原始处理的工具
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim 
batch_size = 64
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,),(0.3081,))
])
train_dataset = datasets.MNIST(root = './data',train = True,download=True,transform=transform)
train_loader = DataLoader(train_dataset,shuffle = True ,batch_size = batch_size)
test_dataset = datasets.MNIST(root = './data',train = False,download=True,transform=transform)
test_loader = DataLoader(test_dataset,shuffle = False ,batch_size = batch_size)
class ResidualBlock(torch.nn.Module):
    def __init__(self,channels):
        super(ResidualBlock,self).__init__()
        self.channels = channels
        self.conv1 = torch.nn.Conv2d(channels,channels,kernel_size=3,padding=1)
        self.conv2 = torch.nn.Conv2d(channels,channels,kernel_size=3,padding=1)
        
    def forward(self,x):
        y = F.relu(self.conv1(x))
        y = self.conv2(y)
        return F.relu(x+y)
class Net(torch.nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = torch.nn.Conv2d(1,16,kernel_size=5)
        self.conv2 = torch.nn.Conv2d(16,32,kernel_size=5)
        self.pooling = torch.nn.MaxPool2d(2)
        
        self.rblock1 = ResidualBlock(16)
        self.rblock2 = ResidualBlock(32)
        
        
        self.fc = torch.nn.Linear(512,10)
    
    def forward(self,x):
        in_size = x.size(0)
        x = self.pooling(F.relu(self.conv1(x)))
        x = self.rblock1(x)
        x = self.pooling(F.relu(self.conv2(x)))
        x = self.rblock2(x)
        x = x.view(in_size,-1)   #flatten
        x = self.fc(x)
        return x
model = Net()
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
def train(epoch):
    running_loss = 0.0
    model.train()
    for batch_idx,data in enumerate(train_loader,0):
        inputs,target = data
        #print(inputs.shape)
        optimizer.zero_grad()
        
        #向前传播
        outputs = model(inputs)
        loss = criterion(outputs,target)
        loss.backward()
        optimizer.step()
        
        running_loss += loss.item()
        if batch_idx % 300 == 299:
            print('[%d,%5d] loss:%.3f' %(epoch +1 ,batch_idx+1,running_loss/300))
            running_loss = 0.0
for epoch in range(10):
    train(epoch)

 2.Googlenet

1)网络结构

模型出发点:不知道哪个卷积核尺寸最好,所有就需要不同的卷积核求特征图,然后将特征图进行拼接。

注意:每个卷积层产生的特征图,c可以不一样,但是w,h要一样。

我们来看一下1*1的卷积核

这个明显更像是加权求和形式的一种信息融合。每个像素点的信息都不包含其他临近像素的信息。

 核心网络结构

 2)核心代码

class InceptionA(nn.Module):
    def __init__(self,in_channels):
        super(InceptionA,self).__init__()
        self.branch1x1 = nn.Conv2d(in_channels,16,kernel_size=1)
        
        self.branch5x5_1 = nn.Conv2d(in_channels,16,kernel_size=1)
        self.branch5x5_2 = nn.Conv2d(16,24,kernel_size=5,padding=2)
        
        self.branch3x3_1 = nn.Conv2d(in_channels,16,kernel_size=1)
        self.branch3x3_2 = nn.Conv2d(16,24,kernel_size=3,padding=1)
        self.branch3x3_3 = nn.Conv2d(24,24,kernel_size=3,padding=1)
        
        self.branch_pool = nn.Conv2d(in_channels,24,kernel_size=1)
    
    def forward(self,x):
        branch1x1 = self.branch1x1(x)
        
        branch5x5 = self.branch5x5_1(x)
        branch5x5 = self.branch5x5_2(branch5x5)
        
        branch3x3 = self.branch3x3_1(x)
        branch3x3 = self.branch3x3_2(branch3x3)
        branch3x3 = self.branch3x3_3(branch3x3)
        
        branch_pool = F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)
        branch_pool = self.branch_pool(branch_pool)
        
        outputs = [branch1x1,branch5x5,branch3x3,branch_pool]
        
        return torch.cat(outputs,dim=1)
        

class Net(nn.Module):
    def  __init__(self):
        super(Net,self).__init__()
        self.conv1 = nn.Conv2d(1,10,kernel_size=5)
        self.conv2 = nn.Conv2d(88,20,kernel_size=5)
            
        self.incep1 = InceptionA(in_channels = 10)
        self.incep2 = InceptionA(in_channels = 20)
            
        self.mp = nn.MaxPool2d(2)
        self.fc = nn.Linear(1408,10)
    def forward(self,x):
         in_size = x.size(0)
         x = F.relu(self.mp(self.conv1(x)))
         x = self.incep1(x)
         x = F.relu(self.mp(self.conv2(x)))
         x = self.incep2(x)
         x = x.view(in_size,-1)
         s = self.fc(x)
         return x
model = Net()

3.mobilenet

1)网络结构

该模型用到了深度分离卷积, 该卷积可以分成两步Depthwise Convolution和Pointwise Convolution两部分构成。

 

Depthwise Convolution的计算非常简单,它对输入feature map的每个通道分别使用一个卷积核,然后将所有卷积核的输出再进行拼接得到它的最终输出。因为卷积操作的输出通道数等于卷积核的数量,而Depthwise Convolution中对每个通道只使用一个卷积核,所以单个通道在卷积操作之后的输出通道数也为1。那么如果输入feature map的通道数为N(如图1.1所示),对N个通道分别单独使用一个卷积核之后便得到N个通道为1的feature map。再将这N个feature map按顺序拼接便得到一个通道为N的输出feature map。

Pointwise Convolution实际为1×1卷积,在DSC中它起两方面的作用。第一个作用是让DSC能够自由改变输出通道的数量;第二个作用是对Depthwise Convolution输出的feature map进行通道融合。

 

 

2)核心代码

class MobileNet(nn.Module):
    def __init__(self,inp,oup,stride):
        super(MobileNet,self).__init__()
        self.dw = torch.nn.Conv2d(inp,inp,kernel_size=3,stride=stride,padding=1,groups=inp,bias=False)
        self.bn1 = torch.nn.BatchNorm2d(inp)
        self.pw = torch.nn.Conv2d(inp,oup,kernel_size=1,stride=1,padding=0,bias=False)
        self.bn2 = torch.nn.BatchNorm2d(oup)
    def forward(self,x):
        x = F.relu(self.bn1(self.dw(x)))
        x = F.relu(self.bn2(self.pw(x)))
        return x
class Net(nn.Module):
    def  __init__(self):
        super(Net,self).__init__()
        self.conv1 = nn.Conv2d(1,32,kernel_size=3,stride=2,padding=1,bias=False) 
        self.bn1 = torch.nn.BatchNorm2d(32)
        
        self.m1 = MobileNet(32,64,1)
        self.m2 = MobileNet(64,128,2)
        self.m3 = MobileNet(128,128,1)
        
        self.mp = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Linear(128,10)  
    def forward(self,x):
         in_size = x.size(0)
         x = F.relu(self.bn1(self.conv1(x)))
         x = self.m1(x)
         x = self.m2(x)
         x = self.m3(x)
         print(x.shape)
         x = self.mp(x)
         x = x.view(in_size,-1)
         x = self.fc(x)
         return x
model = Net()

4.SqueezeNet

1)网络结构

 

 2)核心代码

class Fire(torch.nn.Module):
    def __init__(self,inp,squ_outp,e1x1_outp,e3x3_outp):
        super(Fire,self).__init__()
        self.squeeze  = torch.nn.Conv2d(inp,squ_outp,kernel_size=1)
        self.conve1x1 = torch.nn.Conv2d(squ_outp,e1x1_outp,kernel_size=1)
        self.conve3x3 = torch.nn.Conv2d(squ_outp,e3x3_outp,kernel_size=3,padding=1)
    def forward(self,x):
        x = F.relu(self.squeeze (x))
        x1 = F.relu(self.conve1x1(x))
        x3 = F.relu(self.conve3x3(x))
        
        return torch.cat([x1,x3],1)
        
class Net(torch.nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = torch.nn.Conv2d(1,32,kernel_size=3,stride=2)
        self.fire1 = Fire(32,16,64,64)
        self.fire2 = Fire(128,16,64,64)
        self.fire3 = Fire(128,16,64,64)
        self.final_conv = torch.nn.Conv2d(128,10,kernel_size=1)
        self.classifier = torch.nn.Sequential(
            torch.nn.Dropout(p=0.5),
            self.final_conv,
            torch.nn.ReLU(inplace=True),
            torch.nn.AdaptiveAvgPool2d((1, 1))
        )
        self.pooling = torch.nn.MaxPool2d(kernel_size=3,stride=2,ceil_mode=True)
        self.fc = torch.nn.Linear(320,10)
    
    def forward(self,x):
        batch_size = x.size(0)
        x = self.pooling(F.relu(self.conv1(x)))
        x = self.fire1(x)
        x = self.pooling(self.fire2(x))
        x = self.fire3(x)
        x = self.classifier(x)
        return torch.flatten(x, 1)   

model = Net()

5.ShuffleNet

1)利用矩阵的转置进行Shuffle(通道重排)

首先看一个简单的例子

实现通道重排的代码如下:

 效果如下:将每个组特征图打乱(每个组是三个特征图)

 2)分组卷积

3)核心单元SHUFFLENETUNIT

ShuffleNet的基本单元是在一个残差单元的基础上改进而成的。如图a所示,这是一个包含3层的残差单元:首先是1x1卷积,然后是3x3的depthwise convolution(DWConv,主要是为了降低计算量),这里的3x3卷积是瓶颈层(bottleneck),紧接着是1x1卷积,最后是一个短路连接,将输入直接加到输出上。

现在,进行如下的改进:

将密集的1x1卷积替换成1x1的group convolution,不过在第一个1x1卷积之后增加了一个channel shuffle操作。值得注意的是3x3卷积后面没有增加channel shuffle,按paper的意思,对于这样一个残差单元,一个channel shuffle操作是足够了。还有就是3x3的depthwise convolution之后没有使用ReLU激活函数。改进之后如图b所示。

对于残差单元,如果stride=1时,此时输入与输出shape一致可以直接相加,而当stride=2时,通道数增加,而特征图大小减小,此时输入与输出不匹配。一般情况下可以采用一个1x1卷积将输入映射成和输出一样的shape。但是在ShuffleNet中,却采用了不一样的策略,如图c所示:对原输入采用stride=2的3x3 avg pool,这样得到和输出一样大小的特征图,然后将得到特征图与输出进行连接(concat),而不是相加。这样做的目的主要是降低计算量与参数大小。

 

 

总结一下,unitA输出的shape和输入x的shape是一样的。

unitB通道数有变化,特征图大小缩小了一半。

4)核心代码

def shuffle_channels(x, groups):
    """shuffle channels of a 4-D Tensor"""
    batch_size, channels, height, width = x.size()
    assert channels % groups == 0
    channels_per_group = channels // groups
    # split into groups
    x = x.view(batch_size, groups, channels_per_group,
               height, width)
    # transpose 1, 2 axis
    x = x.transpose(1, 2).contiguous()
    # reshape into orignal
    x = x.view(batch_size, channels, height, width)
    return x
class ShuffelUnitA(torch.nn.Module):
    def __init__(self,in_channels, out_channels, groups=3):
        super(ShuffelUnitA,self).__init__()
        assert in_channels == out_channels
        assert out_channels % 4 == 0
        bottleneck_channels = out_channels // 4
        self.groups = groups
        self.group_conv1x1_1 = nn.Conv2d(in_channels, bottleneck_channels,kernel_size=1, groups=groups, stride=1)
        self.bn1 = nn.BatchNorm2d(bottleneck_channels)
        self.depthwise_conv = nn.Conv2d(bottleneck_channels,bottleneck_channels,kernel_size=3, padding=1, stride=1,groups=bottleneck_channels)
        self.bn2 = nn.BatchNorm2d(bottleneck_channels)
        self.group_conv1x1_2 = nn.Conv2d(bottleneck_channels, out_channels,kernel_size=1, groups=groups, stride=1)
        self.bn3 = nn.BatchNorm2d(out_channels)
    def forward(self, x):
        out = self.group_conv1x1_1(x)
        out = F.relu(self.bn1(out))
        out = shuffle_channels(out,groups=self.groups)
        out = self.depthwise_conv(out)
        out = self.bn2(out)
        out = self.group_conv1x1_2(out)
        out = self.bn3(out)
        out = F.relu(x+out)
        return out
class ShuffelUnitB(torch.nn.Module):
    def __init__(self,in_channels, out_channels, groups=3):
        super(ShuffelUnitB,self).__init__()
        out_channels -= in_channels
        assert out_channels % 4 == 0
        bottleneck_channels = out_channels // 4
        self.groups = groups
        self.group_conv1x1_1 = nn.Conv2d(in_channels, bottleneck_channels,kernel_size=1, groups=groups, stride=1)
        self.bn1 = nn.BatchNorm2d(bottleneck_channels)
        self.depthwise_conv = nn.Conv2d(bottleneck_channels,bottleneck_channels,kernel_size=3, padding=1, stride=2,groups=bottleneck_channels)
        self.bn2 = nn.BatchNorm2d(bottleneck_channels)
        self.group_conv1x1_2 = nn.Conv2d(bottleneck_channels, out_channels,kernel_size=1, groups=groups, stride=1)
        self.bn3 = nn.BatchNorm2d(out_channels)
    def forward(self, x):
        out = self.group_conv1x1_1(x)
        out = F.relu(self.bn1(out))
        out = shuffle_channels(out,groups=self.groups)
        out = self.depthwise_conv(out)
        out = self.bn2(out)
        out = self.group_conv1x1_2(out)
        out = self.bn3(out)
        x = F.avg_pool2d(x, 3, stride=2, padding=1)
        out = F.relu(torch.cat([x,out],1))
        return out
class Net(torch.nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = torch.nn.Conv2d(1,24,kernel_size=3,stride=2,padding=1)
        stage2_seq = [ShuffelUnitB(24, 240, groups=3)] + [ShuffelUnitA(240, 240, groups=3) for i in range(3)]
        self.stage2 = nn.Sequential(*stage2_seq)
        stage3_seq = [ShuffelUnitB(240, 480, groups=3)] + [ShuffelUnitA(480, 480, groups=3) for i in range(7)]
        self.stage3 = nn.Sequential(*stage3_seq)
        stage4_seq = [ShuffelUnitB(480, 960, groups=3)] + [ShuffelUnitA(960, 960, groups=3) for i in range(3)]
        self.stage4 = nn.Sequential(*stage4_seq)
        self.fc = torch.nn.Linear(960,10)
    
    def forward(self,x):
        batch_size = x.size(0)
        print('nihao')
        x = self.conv1(x)
        x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1)
        x = self.stage2(x)
        x = self.stage3(x)
        x = self.stage4(x)
        x = F.avg_pool2d(x, 1)
        x = x.view(batch_size,-1)   #flatten
        x = self.fc(x)
        return x

model = Net()

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

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

相关文章

【REACT-redux】

1. redux介绍 1.1 描述 Redux最主要是用作应用状态的管理。简言之,Redux用一个单独的常量状态树(state对象)保存这一整个应用的状态,这个对象不能直接被改变。当一些数据变化了,一个新的对象就会被创建(使…

JDK SPI 和 Dubbo SPI

SPI (Service Provider Interface),简单翻译就是服务提供接口,这里的“服务”泛指任何一个可以提供服务的功能、模块、应用或系统,会预留一些口子或者扩展点,只要按照既定的规范去开发,就可以动…

MES和金蝶云星空接口打通对接实战

四化智造MES(WEB)和金蝶云星空接口打通对接实战数据源平台:四化智造MES(WEB)MES建立统一平台上通过物料防错防错、流程防错、生产统计、异常处理、信息采集和全流程追溯等精益生产和精细化管理,帮助企业合理安排生产排…

机器视觉_HALCON_HDevelop用户指南_2.Getting Started

文章目录前言二、Getting Started2.1. 运行HDevelop2.2. 运行示例程序前言 标题本来想用“开始使用”或“快速上手”,不过感觉怪怪的,干脆就叫Getting Started吧,因为许多开发手册,开始上手的那节就叫这个名字。 本文是接上一篇…

【人工智能原理自学】LSTM网络:自然语言处理实践

😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文讲解LSTM网络:自然语言处理实践,一起卷起来叭! 目录一、“RNN”二、编程实验一、“RNN” 上节课我们利用词嵌入把句子转化为词向量序列…

手把手本地搭建服务器笔记1

需要的下载的东西: vmware (百度网盘)银河麒麟镜像xshell,xftp安装vmware: 下载的包里有密钥,安装的时候就直接把密钥扔里面就好了 镜像处理: vmware左上角文件-新建虚拟机-典型,下一步 -安装程序光盘映像文件&am…

基于嵌入式物联网技术的智慧病房方案设计

文章目录前言1、要求2、系统设计3、功能模块3、系统功能模块图一、stm32控制模块原理图二、各功能模块的实现1、整个系统的基本配置2、RTOS多任务1、设计线程2、配置主函数代码3、温湿度读取模块(I2C)4、LED定时开关灯(pwm)5、按键实现报警信号6、脉搏&血氧数据读取7、UART…

【HTML】基础的入门学习

HTML 菜鸟教程 简介 一般结构&#xff1a; <!DOCTYPE html> 声明为 HTML5 文档<html> 元素是 HTML 页面的根元素<head> 元素包含了文档的元&#xff08;meta&#xff09;数据&#xff0c;如 <meta charset"utf-8"> 定义网页编码格式为 ut…

proteus仿真软件中芯片的命名规则与封装方法(详细版)

第一&#xff1a;PCB封装库命名规则 1、集成电路&#xff08;直插&#xff09; 用DIP-引脚数量尾缀来表示双列直插封装​ 尾缀有N和W两种,用来表示器件的体宽​ 为体窄的封装&#xff0c;体宽300mil,引脚间距2.54mm​ 为体宽的封装, 体宽600mil,引脚间距2.54mm​ 如&#…

11、关联数据库

文章目录11、关联数据库11.1 常规方式11.2 常规操作【尚硅谷】idea实战教程-讲师&#xff1a;宋红康 生活是属于每个人自己的感受&#xff0c;不属于任何别人的看法 11、关联数据库 11.1 常规方式 找到数据库选项&#xff1a; 添加指定数据库&#xff1a; 配置MySQL数据库…

5. 网络编程之UDP编程

1. UDP协议的特点 相比与TCP协议来说&#xff0c;UDP协议就显得相对比较简单了。 (1) UDP是无连接的   即发送数据之前不需要建立连接(当然&#xff0c;发送数据结束时也没有连接可释放)&#xff0c;因此减少了开销和发送数据之前的时延。 (2) UDP使用尽最大努力交付   即…

78、Points2NeRF: Generating Neural Radiance Fields from 3D point cloud

简介 github&#xff1a;https://github.com/gmum/points2nerf 由于点云的大小和复杂性&#xff0c;处理这些点云具有挑战性&#xff0c;现有的方法通过将网格拟合到点云并渲染来解决这个问题&#xff0c;这种方法导致结果可视化的保真度降低&#xff0c;并遗漏了在计算机图形…

HashTable HashMap ConcurrentHashMap 的介绍以及区别

目录 &#x1f407;今日良言:投资自己才是最好的投资 &#x1f409;一.HashMap. &#x1f415;二.HashTable &#x1f40d;三.ConcurrentHashMap &#x1f402;四.三者的区别 &#x1f407;今日良言:投资自己才是最好的投资 时隔四十多天,今天博主要更新了. 后续内容也是精…

[机器学习]损失函数DLC

一、损失函数的概念 损失函数(Loss Function)是用于评估预测结果和真实结果之间差距的一个公式&#xff0c;为模型优化指明方向。在模型优化过程中一般表述为&#xff1a;或 与针对整个训练集的代价函数(Cost Function)不同&#xff0c;损失函数通常仅针对单个训练样本。可以归…

RK3568平台开发系列讲解(驱动基础篇)Linux 内核源码介绍

🚀返回专栏总目录 文章目录 一、目录树概览二、快速确定主板关联代码2.1、基础代码2.2、驱动代码沉淀、分享、成长,让自己和他人都能有所收获!😄 📢进行嵌入式 Linux 产品开发,往往需要对内核进行裁剪和定制,以满足嵌入式产品的功能和性能需求。 一、目录树概览 解压…

Python---学生管理系统(pyinstaller)

专栏&#xff1a;python 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;本专栏主要更新一些python的基础知识&#xff0c;也会实现一些小游戏和通讯录&#xff0c;学时管理系统之类的&#xff0c;有兴趣的朋友可以关注一下。 学生管理系统前言创建入口函数新增学生insert展…

行为型模式-迭代器模式

1.概述 定义&#xff1a;提供一个对象来顺序访问聚合对象中的一系列数据&#xff0c;而不暴露聚合对象的内部表示。 2.结构 迭代器模式主要包含以下角色&#xff1a; 抽象聚合&#xff08;Aggregate&#xff09;角色&#xff1a;定义存储、添加、删除聚合元素以及创建迭代器…

实战案例:Python批量识别银行卡号码并且写入Excel,初学者也可以轻松使用~

大家好&#xff0c;这里是程序员晚枫&#xff0c; 今天我们继续学习Python自动化办公&#xff1a;每次有新员工入职&#xff0c;都要收集大量的工资卡信息&#xff0c;并且生成Excel文档&#xff0c;能不能用Python准确、快速地解决呢&#xff1f; 今天我们就来学习一下&…

【CCNA | 网络模拟器CPT系列】Cisco Packet Tracer 8.2.0 的安装 Ⅰ

目录1. 下载 Cisco Packet Tracer2. 安装 Cisco Packet Tracer&#xff08;1&#xff09;许可协议界面&#xff08;2&#xff09;选择安装目录&#xff08;3&#xff09;选择开始菜单文件夹&#xff08;4&#xff09;选择附加任务&#xff08;5&#xff09;确认设置选择&#x…

K8S环境安装

K8S环境安装 下面是环境的主机名和IP 主机名ipk8smaster192.168.68.150k8snode1192.168.68.151k8snode2192.168.68.152 1、安装docker 配置yum源 sudo yum install -y yum-utils sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/d…