Advanced CNN

news2024/9/21 16:17:59

文章目录

  • 回顾
  • 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]

在这里插入图片描述

练习

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

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

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

相关文章

第一集《修道宗范》

当家师父慈悲,诸位法师、诸位新戒、诸位在家菩萨,阿弥陀佛 今天学人跟大家研究的主题是《修道宗范》。很多人都会认为:所有的宗教都是劝人为善,所以佛教的修学跟一般的宗教,完全是一样的。其实,这个观念只…

Centos慢慢长大(一)

1、写在前面 这将是一个系列性的文章。可能更多的是记录我在学习的过程中的一些感悟吧。我想强调的是在这一系列文章里我会从最小化的安装开始,然后逐渐的增加需要安装的软件。就象一个婴儿的诞生,慢慢的学走路、学说话、学使用筷子。。。。。。 这将是一…

离谱题 3236:练39.1 书香阁座位

3236正常写法 #include<bits/stdc.h> using namespace std; int main() {int sum,a,b;a1;b10;sumb;cout<<a<<" "<<b;cout<<" "<<sum<<endl;do{a;b2;sumx;cout<<a<<" "<<b<<&…

升级企业战略,思腾合力布局智能生产基地

一直专注于人工智能领域&#xff0c;提供云计算、AI服务器、AI工作站、系统集成、产品定制、软件开发、边缘计算等产品和整体解决方案&#xff0c;致力于成为行业领先的人工智能基础架构解决方案商。 升级企业战略 布局智能生产基地 “十四五”时期&#xff0c;是乘势而上打造…

力扣hot100 不同路径 多维DP 滚动数组 数论

Problem: 62. 不同路径 文章目录 思路解题方法复杂度朴素DP 思路 讲述看到这一题的思路 解题方法 &#x1f468;‍&#x1f3eb; 卡尔一题三解 复杂度 时间复杂度: &#xff1a; O ( n m ) O(nm) O(nm) 空间复杂度: O ( n m ) O(nm) O(nm) 朴素DP class Solution {p…

【Qt学习笔记】(一)初识Qt

Qt学习笔记 1 使用Qt Creator 新建项目2 项目代码解释3 创建第一个 Hello World 程序4 关于内存泄漏问题5 Qt 中的对象树6 关于 qDebug&#xff08;&#xff09;的使用7 使用其他方式创建一个 Hello World 程序&#xff08;编辑框和按钮方式&#xff09;8 关于 Qt 中的命名规范…

操作系统基础:死锁

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;OS从基础到进阶 &#x1f426;1 死锁的概念&#x1f9a2;1.1 总览&#x1f9a2;1.2 什么是死锁&#x1f9a2;1.3 死锁、饥饿、死循环的区别&#x1f427;1.3.1 概念&#x1f427;1.3.2 区别…

#RAG|NLP|Jieba|PDF2WORD# pdf转word-换行问题

文档在生成PDF时,文宁都发生了什么。本文讲解了配置对象、resources对象和content对象的作用,以及字体、宇号、坐标、文本摆放等过程。同时,还解释了为什么PDF转word或转文字都是一行一行的以及为什么页眉页脚的问题会加大识别难度。最后提到了文本的编码和PDF中缺少文档结构标…

7zip压缩包乱码问题

打开压缩包查看或解压时&#xff0c;发现其中的文件名显示乱码。 经网络搜索&#xff0c;判断是编码的问题。因为我OS是UTF-8&#xff0c;而压缩包编码是CP936。 解决方法只能用命令行&#xff0c;-mcp指定了code page&#xff1a; "c:\Program Files\7-Zip\7z.exe&quo…

阿里云智能集团副总裁安筱鹏:企业数字化的终局是什么?

以下文章来源于数字化企业 &#xff0c;作者安筱鹏博士 回答数字化终局追问的起点是&#xff0c;企业需要重新定义我是谁。成为有竞争力的行业领导厂商&#xff0c;你应当成为一个客户运营商&#xff0c;即能够实时洞察、实时满足客户需求&#xff0c;追求极致的客户体验。而要…

12.scala下划线使用总结

目录 概述实践变量初始化导包引入方法转变为函数用户访问Tuple元素简化函数参数传递定义偏函数变长参数 结束 概述 实践 变量初始化 在Scala中&#xff0c;变量在声明时需要显式指定初始值。可以使用下划线为变量提供初始值&#xff0c;但这种语法仅限于成员变量&#xff0c;…

抠门精出游记第三天

熊野古道&#xff0c;最早我是在新加坡地铁站看到的日本旅游广告上出现的&#xff0c;我觉得以前很多次自由行都是打卡式的&#xff0c;觉得确实需要一些深度游&#xff0c;而且趁着身体状态还可以&#xff0c;反正就这么种草了。 然后小红书上看到不少有关行程介绍&#xff0c…

npm i 遇到了 npm ERR! code CERT_HAS_EXPIRED

npm i 遇到了 npm ERR! code CERT_HAS_EXPIRED 更新你的系统时间【命令 date】。确保你的计算机上的时间和时区设置正确&#xff0c;并且与当前时间相符。 清除你的 npm 缓存。使用 npm cache clean --force 命令清除你的 npm 缓存&#xff0c;关闭ssl验证&#xff0c;并重新运…

使用 Docker 部署超级马里奥 Web 游戏

一、游戏介绍 超级马里奥 是一款经典闯关游戏&#xff0c;也叫做超级玛丽。由红白机 FC 游戏移植而来&#xff0c;简约的游戏画面&#xff0c;加上简单的操作方式&#xff0c;让你重温儿时的经典。 二、环境检查 1&#xff09;检查操作系统版本 检查本次实践的操作系统版本 ca…

使用VScode远程连接Ubuntu

君衍. 一、环境准备二、配置VScode三、远程连接Ubuntu 平常远程连接服务器的工具有很多&#xff0c;比如Moba、Xshell、putty、甚至CRT都可以进行远程连接服务器&#xff0c;但是他们的本质是相同的&#xff0c;都是使用ssh来进行远程连接。 这里我们之所以要使用VScode远程连接…

Debezium发布历史100

原文地址&#xff1a; https://debezium.io/blog/2020/12/17/debezium-1-4-cr1-released/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Debezium 1.4.0.CR1 发布 2020 年 12 月 17 日 作者&#xff1a; 克里斯…

SpringCloud Gateway(4.1.0) 返回503:原因分析与解决方案

文章目录 一、环境版本二、原因分析三、解决方案 一、环境版本 Versionspring-cloud-dependencies2023.0.0spring-cloud-starter-gateway4.1.0Nacosv2.3.0 二、原因分析 在 Spring Cloud Gateway 的早期版本中&#xff0c;Ribbon 被用作默认的负载均衡器。随着Spring Cloud的…

如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图二

Mermaid 系列 如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图一 1. 如何使用 Mermaid 生成图表 Mermaid 是一个基于 JavaScript 的工具&#xff0c;可将 Markdown 样式的文本转换为动态图表&#xff0c;让您可以毫不费力地创建和修改它们。 Mermaid 使使用简单的文…

爬虫学习笔记-scrapy安装及第一个项目创建问题及解决措施

1.安装scrapy pycharm终端运行 pip install scrapy -i https://pypi.douban.com/simple 2.终端运行scrapy startproject scrapy_baidu,创建项目 问题1:lxml版本低导致无法找到 解决措施:更新或者重新安装lxml 3.项目创建成功 4.终端cd到项目的spiders文件夹下,cd scra…

【制作100个unity游戏之23】实现类似七日杀、森林一样的生存游戏5(附项目源码)

本节最终效果演示 文章目录 本节最终效果演示系列目录前言修改鼠标光标和中心提示图鼠标光标素材修改默认鼠标光标修改中心提示图 拾取提示弹窗简单绘制UI拾取弹窗功能 源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使…