Advanced CNN

文章目录

  • 回顾
  • Google Net
    • Inception
    • 1*1卷积
    • Inception模块的实现
    • 网络构建
    • 完整代码
  • ResNet
    • 残差模块 Resedual Block
    • 残差网络的简单应用
    • 残差实现的代码
  • 练习

回顾

这是一个简单的线性的卷积神经网络
在这里插入图片描述
然而有很多更为复杂的卷积神经网络。

Google Net

Google Net 也叫Inception V1,是由Inception模块堆叠而成的卷积神经网络。
详情请见我的另一篇博客
在这里插入图片描述

Inception

在这里插入图片描述
基本思想

  • 首先通过1x1卷积来降低通道数把信息聚集
  • 再进行不同尺度的特征提取以及池化,得到多个尺度的信息
  • 最后将特征进行叠加输出
  • (官方说法:可以将稀疏矩阵聚类为较为密集的子矩阵来提高计算性能)
    主要过程:
  • 在3x3卷积和5x5卷积前面、3x3池化后面添加1x1卷积,将信息聚集且可以有效减少参数量(称为瓶颈层);
  • 下一层block就包含1x1卷积,3x3卷积,5x5卷积,3x3池化(使用这样的尺寸不是必需的,可以根据需要进行调整)。这样,网络中每一层都能学习到“稀疏”(3x3、5x5)或“不稀疏”(1x1)的特征,既增加了网络的宽度,也增加了网络对尺度的适应性;
  • 通过按深度叠加(deep concat)在每个block后合成特征,获得非线性属性。
  • 注:在进行卷积之后都需要进行ReLU激活,这里默认未注明。

1*1卷积

  • 1*1卷积:卷积核大小为1的卷积,主要用于改变通道数,而不会改变特征图W、H。
  • 也可以用于进行特征融合。
  • 在执行计算昂贵的 3 x 3 卷积和 5 x 5 卷积前,往往会使用 1 x 1 卷积来减少计算量。

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

Inception模块的实现

在这里插入图片描述
注意:只有所有特征图大小一样(W、H一样),才能进行拼接,通道数可以不同。
在这里插入图片描述

网络构建

# design model using class
class InceptionA(nn.Module):
    def __init__(self, in_channels):
        super(InceptionA, self).__init__()
        self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积

        self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
        self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)#padding=2,大小不变

        self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
        self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)#padding=1,大小不变
        self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)#padding=1,大小不变

        self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)#1*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)  # b,c,w,h  c对应的是dim=1


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.incep1 = InceptionA(in_channels=10)  # 与conv1 中的10对应

        self.conv2 = nn.Conv2d(88, 20, kernel_size=5)  # 88 = 24x3 + 16
        self.incep2 = InceptionA(in_channels=20)  # 与conv2 中的20对应

        self.mp = nn.MaxPool2d(2)
        self.fc = nn.Linear(1408, 10)#1408=88*4*4,是x展开之后的值;其实可以不用自己计算

    def forward(self, x):
        in_size = x.size(0)
        x = F.relu(self.mp(self.conv1(x)))#W、H=12
        x = self.incep1(x)
        x = F.relu(self.mp(self.conv2(x)))#W、H=4
        x = self.incep2(x)
        x = x.view(in_size, -1)
        x = self.fc(x)

        return x

完整代码

import numpy as np
import torch
import torch.nn as nn
from matplotlib import pyplot as plt
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

# prepare dataset

batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])  # 归一化,均值和方差

train_dataset = datasets.MNIST(root='dataset', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_dataset = datasets.MNIST(root='dataset', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)


# design model using class
class InceptionA(nn.Module):
    def __init__(self, in_channels):
        super(InceptionA, self).__init__()
        self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积

        self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
        self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)#padding=2,大小不变

        self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
        self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)#padding=1,大小不变
        self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)#padding=1,大小不变

        self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)#1*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)  # b,c,w,h  c对应的是dim=1


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.incep1 = InceptionA(in_channels=10)  # 与conv1 中的10对应

        self.conv2 = nn.Conv2d(88, 20, kernel_size=5)  # 88 = 24x3 + 16
        self.incep2 = InceptionA(in_channels=20)  # 与conv2 中的20对应

        self.mp = nn.MaxPool2d(2)
        self.fc = nn.Linear(1408, 10)#1408=88*4*4,是x展开之后的值;其实可以不用自己计算

    def forward(self, x):
        in_size = x.size(0)
        x = F.relu(self.mp(self.conv1(x)))#W、H=12
        x = self.incep1(x)
        x = F.relu(self.mp(self.conv2(x)))#W、H=4
        x = self.incep2(x)
        x = x.view(in_size, -1)
        x = self.fc(x)

        return x


model = Net()

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#定义device,如果有GPU就用GPU,否则用CPU

model.to(device)
# 将所有模型的parameters and buffers转化为CUDA Tensor.

criterion=torch.nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
def train(epoch):
    running_loss=0.0
    for batch_id,data in enumerate(train_loader,0):
        inputs,target=data
        inputs,target=inputs.to(device),target.to(device)
        #将数据送到GPU上
        optimizer.zero_grad()

        # forward + backward + update

        outputs=model(inputs)
        loss=criterion(outputs,target)
        loss.backward()
        optimizer.step()
        running_loss +=loss.item()
        if batch_id% 300==299:
            print('[%d,%5d] loss: %.3f' % (epoch+1,batch_id,running_loss/300))
            running_loss=0.0


accracy = []
def test():
    correct=0
    total=0
    with torch.no_grad():
        for data in test_loader:
            inputs,target=data
            inputs,target=inputs.to(device),target.to(device)
            #将数据送到GPU上
            outputs=model(inputs)
            predicted=torch.argmax(outputs.data,dim=1)
            total+=target.size(0)
            correct+=(predicted==target).sum().item()
    print('Accuracy on test set : %d %% [%d/%d]'%(100*correct/total,correct,total))
    accracy.append([100*correct/total])

if __name__ == '__main__':
    for epoch in range(10):
        train(epoch)
        test()

    x=np.arange(10)
    plt.plot(x, accracy)
    plt.xlabel("Epoch")
    plt.ylabel("Accuracy")
    plt.grid()
    plt.show()

训练结果:
在这里插入图片描述

ResNet

卷积层是不是越多越好?

  • 在CIFAR数据集上利用20层卷积和56层卷积进行训练,56层卷积的loss还要大一些。
  • 这是因为网络层数太多,可能会出现梯度消失和梯度爆炸
  • 梯度消失和梯度爆炸:是在反向传播计算梯度时,梯度太小或者太大,随着网络层数不断加深,梯度值是呈现指数增长,变得趋近于0或者很大。比如说 0. 4 n 0.4^n 0.4n,n=100时,值就已结很小了;比如说 1. 5 n 1.5^n 1.5n,n=100时也非常大了。
    在这里插入图片描述

残差模块 Resedual Block

**残差连接:

  • **很简单!就是一个跳连接,将输入X和卷积之后的特征图相加就行了,即y=x+f(x)。
  • 相加需要两个特征图的大小和通道数都一样。
  • 可以获得更丰富的语义特征,避免梯度消失和爆炸。
  • 非常常用!!!是必须学会的一个小技巧。
    在这里插入图片描述
    在这里插入图片描述
    残差连接,可以跨层进行跳连接!发挥创造力炼丹吧!
    在这里插入图片描述

残差网络的简单应用

在这里插入图片描述

残差实现的代码

在这里插入图片描述

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)
        self.conv3=torch.nn.Conv2d(channels,channels,kernel_size=1)

    def forward(self,x):
        y=F.relu(self.conv1(x))
        y=self.conv2(y)
        return F.relu(x+y)

接下来,笔交给你了!
在这里插入图片描述
我的训练结果:

Accuracy on test set : 98 % [9872/10000]
[7,  299] loss: 0.027
[7,  599] loss: 0.032
[7,  899] loss: 0.032
Accuracy on test set : 98 % [9874/10000]
[8,  299] loss: 0.028
[8,  599] loss: 0.026
[8,  899] loss: 0.026
Accuracy on test set : 99 % [9901/10000]
[9,  299] loss: 0.022
[9,  599] loss: 0.025
[9,  899] loss: 0.027
Accuracy on test set : 99 % [9900/10000]
[10,  299] loss: 0.024
[10,  599] loss: 0.019
[10,  899] loss: 0.027
Accuracy on test set : 98 % [9895/10000]

在这里插入图片描述

练习

请实现以下两种残差结构,并用他们构建网络跑模型。
在这里插入图片描述

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

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

相关文章

轻量式RPC调用日志链路设计方案

导语: 调用链跟踪系统,又称为tracing,是微服务设计架构中,从系统层面对整体的monitoring和profiling的一种技术手 背景说明 由于我们的项目是微服务方向,中后台服务调用链路过深,追踪路径过长,其中某个服务报错或者异…

探索设计模式的魅力:精准解读桥接模式-用桥接模式构建可扩展的软件系统

设计模式专栏:http://t.csdnimg.cn/nolNS 目录 一、了解桥接模式:探索抽象和实现的分离 1.1 开-闭原则 1.2 组合/聚合复用原则 1.3 定义 1.4 用意 1.5 基本思想 1.6 组成部分 1.7 桥梁模式的示意性系统的结构图 二、桥接模式的优势&#xff1a…

torchvision.models._utils.IntermediateLayerGetter()使用

torchvision.models._utils.IntermediateLayerGetter()使用 源码如下: from collections import OrderedDictimport torch from torch import nnclass IntermediateLayerGetter(nn.ModuleDict):"""Module wrapper that ret…

【Tomcat与网络6】 Tomcat是如何扩展Java线程池的?

目录 1.Java 的线程池 2.Tomcat 的线程池 学习Tomcat的时候,有很多绚丽的技术值得我们学习,但是个人认为Tomcat的线程池扩展是最值得研究的一个部分,线程池的应用太广了,也重要了,Java原生线程池的特征我相信很多人都…

matlab中的图窗属性和坐标轴的属性

图窗的Position和Outerposition Position 指定窗口的尺寸和窗口在屏幕中的位置。 Outerposition 指定窗口外轮廓的大小和位置。 两者都是用一个4维向量来定义,格式为[左 底 宽 高]。 可通过set函数修改Position和Outerposition,如下:在屏幕左…

adb 无线连接 操作Android设备

最近集五福活动比较热门 可以用这个工具 用自己擅长的语言写一个循环程序 运行起来就可以 自动帮我们 看视频得福卡了 很方便 while (true) {sleep(mt_rand(15, 25));system(adb shell input swipe 500 2000 500 1000 100); } 1. 首先下载 安卓开发工具 adb adb网盘链接 链接…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Gauge组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Gauge组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Gauge组件 数据量规图表组件,用于将数据展示为环形图表。 子组件 无…

解决H5中IOS手机底部被弹出键盘遮挡问题

在开发移动端的H5应用时,我们经常会遇到一个问题,就是在iOS手机上,当输入框获取焦点并弹出键盘时,键盘会遮挡住页面底部的内容,给用户带来不便。本文将介绍一种很巧妙的解决方案,通过滚动页面的方式&#x…

AI智能分析+明厨亮灶智慧管理平台助力“舌尖上的安全”

春节是中国最重要的传统节日之一,在春节期间,人们聚餐需求激增,餐饮业也迎来了高峰期。在这个时期,餐饮企业需要更加注重食品安全和卫生质量,以保证消费者的健康和权益,明厨亮灶智慧管理成为了餐饮业中备受…

【spring】springcloud中的组件有那些?

🍎个人博客:个人主页 🏆个人专栏:spring ⛳️ 功不唐捐,玉汝于成 目录 正文 我的其他博客 正文 说出主要的组件: Spring Cloud Eureka,服务注册中心,特性有失效剔除、服务保护Spring Cloud Zuul,API服…

【python】使用GtkPaned的程序

一、GTK小部件(widgets) GTK(GIMP Toolkit)是一种广泛使用的图形用户界面工具包,用于创建跨平台的GUI应用程序。它提供了许多构建用户界面的控件,称为"小部件"(widgets)。…

ArrayList集合初始化长度是多少,初始化的时候分配内存空间吗

ArrayList一旦初始化,在内存中就会分配空间吗 是的,当ArrayList在Java中初始化时,即使它没有添加任何元素,也会立即分配内存空间。具体来说,对于默认构造函数创建的ArrayList(即不指定初始容量&#xff09…

idea/webstorm 创建Vue实例 Unresolved type Vue 处理方法

1.电脑本地安装node.js 官网下载 2. 其他: 未排除变量,前期试错(以下步骤配置了,但不确定对解决问题是否有帮助)

EasyExcel根据对应的实体类模板完成多个sheet的写入与读取

1.展示模板一的实体类 import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentRowHeight; import com.alibaba.excel.annotation.write.style.HeadRowH…

(已解决)Properties和Yaml格式互转

工具转换: 推荐转换工具或者下载idea插件yamls yml,properties互转工具:yaml和proper互转工具 插件转换: 下载yaml插件,对需要转换的文件右键选择转换

Redis常用数据类型--String

String 常用命令SETGETMGETMSETSETNXINCR/DECRINCRBY/DECRBYINCRBYFLOATAPPENDGETRANGESETRANGESTRLEN 内部编码典型应用场景 常用命令 SET 将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖,⽆论原来的数据类型是什么。之 前关于此 k…

GIT基础命令使用

远程仓库的使用 HTTPS:零配置,但每次访问需要账号和密码 SSH:需要进行额外的配置配置成功后不需要重复输入账号密码 生成SSH Key ① 打开 Git Bash ②粘贴如下的命令,并将 your_emailexample.com 替换为注册Github账号时填写…

TSINGSEE青犀智能分析网关V4如何利用AI智能算法保障安全生产、监管,掀开安全管理新篇章

旭帆科技的智能分析网关V4内含近40种智能分析算法,包括人体、车辆、消防、环境卫生、异常检测等等,在消防安全、生产安全、行为检测等场景应用十分广泛。如常见的智慧工地、智慧校园、智慧景区、智慧城管等等,还支持抓拍、记录、告警、语音对…

Zookeeper分布式命名服务实战

目录 分布式命名服务 分布式API目录 分布式节点的命名 分布式的ID生成器 分布式的ID生成器方案: 基于Zookeeper实现分布式ID生成器 基于Zookeeper实现SnowFlakeID算法 分布式命名服务 命名服务是为系统中的资源提供标识能力。ZooKeeper的命名服务主要是利用Z…

基于OpenCV的高压电力检测项目案例

一、项目背景与目标 随着高压电力设施的日益增多,传统的巡检方式已无法满足现代电力系统的需求。为此,我们决定利用计算机视觉技术,特别是OpenCV库,开发一个高压电力检测系统。目标是实现自动化、高精度的电力设备检测&#xff0c…