inception网络_TF2.0 ResNet【残差跳连】+ResNet块和Inception块设计思路分析+5种经典卷积神经网络小结+阶段小结...

引言: 因LeNet,AlexNet,VGG16就是卷积层的堆叠,这三个就是在激活函数,BN操作,Dropout操作,卷积核尺寸以及网络层数上不断改进,很好理解;而Inception和ResNet 有其独特的设计和组成单元 。 本文按照设计背景和思路分析这两者的组成单元。 【原文链接配全部经典CNN网络代码】
目录:
  1.  InceptionNet的核心组成——inception块

  2.  ResNet的核心组成——ResNet块

  3.  ResNet块和inception块对比

  4.  5种经典卷积神经网络小结

  5. 小结:神经网络搭建和CNN小结

1.InceptionNet——多路分支合并同一层使用不同尺寸卷积核;引入BN

一.InceptionNet的亮点:

    1.引入了BN操作,缓解梯度消失

    2.同一层使用不同尺寸卷积核,形成四个分支,分支堆叠,提升模型感知力,使用了很多的1*1卷积核。(尺寸越小的卷积核,参数越少,计算量越小)

    3. 上述所言构成了Inception块,是Inception的核心单元。

无论是GooLeNet,即Inception v1,还是Inception的后续版本,如v2,v3,v4,都是基于Inception结构块搭建的。

二. Inception块:

508470b86938a41c52d227a3b8052693.png

       Inception 结构块在同一层网络中使用了多个尺寸的卷积核,可以提取不同特征。

ps:

        1*1卷积核:作用到输入特征的每一个像素点,通过设定少于输入特征图深度的1*1卷积核个数减少了输出特征图的深度,起到了降维作用,减少了参数量和计算量【尺寸越小的卷积核,参数越少,计算量越小】

InceptionNet:

2a99a34bd978829f274a274ea7e8d6eb.png

代码实现和实验结果见:

TF2.0-自作图+代码实现:LeNet,AlexNet,VggNet,Inception经典神经网络

2.ResNet ——层间残差跳连:使神经网络层数加深成为可能

    前四种经典卷积神经网络模型的层数如下[只计算卷积层和全连接层]:

b2f3ff2d070b9f5e01413052566d72b3.png

    通过上一篇文章的实验结果对比,得出暂时性的结论:

5 → 8 →16/19 → 22:通过加深网络层数,取得了越来越好的效果

717fcfcac5b3add3ffc70d8f70e67d79.png

     于是ResNet的大神作者:何凯明,其在cifar10上做了个实验,发现56层卷积网络的错误率要高于20层的错误率!

784a9525ec95b2bc348df5ac80d10bd2.png

他认为,单纯靠卷积网络的堆叠,会造成神经网络的退化

                以至于后面的特征丢失了前边特征的原本模样。

问题:神经网络的退化的原因就是随着网络的加深,特征就会被不断的CBAPD处理处理在处理,到了后边,原来特征本身就会被遗忘,那怎么解决这个问题?

何凯明提出了ResNet块

这一操作有效缓解了神经网络模型堆叠导致的退化

使得神经网络可以向着更深层级发展

92058fe743ebf1097e223ef25a1b2248.png

     正如上图:我们看到x是输入特征图,经过了两层堆叠卷积层,得到非线性输出F(x),我们要解决的问题是我们 还想要把x输入特征图带进来,也要影响到我们的输出H(x) ,这样就能考虑到之前的原始特征了。  那要执行什么操作?+ 加操作。ResNet块中的‘+’:两路特征图对应元素值相加(相当于两个矩阵对应元素值相加) 有两种情况:取决于这个堆叠卷积层有没有对输入特征图x进行缩放 ①输出结果H(x) = 堆叠卷积层输出F(x)+x   (堆叠层输出的F(x)维度和输入特征图维度x一样) ②输出结果H(x) = 堆叠卷积层输出F(x)+W(x) (堆叠层输出的F(x)维度和输入特征图维度x不一样 )

62c45732c0a2483513e2339f13244e71.png

基本组成有了,接下来使用ReNet块来搭建网络 ResNet:

03ad75b0863a58078499b05c4de5bf1b.png

和Inception的实现一样,基本模块被封装在一个class里 代码实现——ResNet块:     将这两种情况封装在一个class里
# 将两种ResNet块封装在一起:ResnetBlock类# 每调用一次ResnetBlock类,生成一个ResNet块#  根据   区别两种情况:#  ①如果是维度不同ResNet块: residual_path = 1,残差#  调用if里的代码,使用1*1的卷积操作,调整输入特征图inputs的尺寸或深度#   将堆叠卷积输出特征y和if语句算出的residual相加 过激活 输出#  ②如果是维度相同的ResNet块:直接将堆叠卷积层输出特征y和输入特征图inputs相加 过激活 输出import tensorflow as tfimport osimport numpy as npfrom matplotlib import pyplot as pltfrom tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Densefrom tensorflow.keras import Modelimport osos.environ['CUDA_VISIBLE_DEVICES'] = '0'config = tf.compat.v1.ConfigProto(allow_soft_placement=True)config.gpu_options.allow_growth = Truesess =tf.compat.v1.Session(config=config)class ResnetBlock(Model):    # 初始 residual_path 为False,默认满足情况②    def __init__(self,filters,strides=1,residual_path=False):        super(ResnetBlock,self).__init__()        self.filters = filters        self.strides = strides        self.residual_path = residual_path        #两层卷积,usebians带上b        self.c1 = Conv2D(filters,(3,3),strides=strides,padding='same',use_bias=False)        self.b1 = BatchNormalization()        self.a1 = Activation('relu')        self.c2 = Conv2D(filters,(3,3),strides =1,padding='same',use_bias=False)        self.b2 = BatchNormalization()        # residual_path 为True时,满足①        #对输入进行向下采样:使用1*1的卷积操作,调整输入特征图inputs的尺寸或深度        if residual_path:            self.down_c1 = Conv2D(filters,(1,1),strides = strides,padding='same',use_bias=False)            self.down_b1 = BatchNormalization()        # 激活        self.a2 = Activation('relu')    def call(self,inputs):        # residual等于输入值本身,即residual =x        residual = inputs        # 将输入通过卷积,BN,A,计算F(x)        x = self.c1(inputs)        x = self.b1(x)        x = self.a1(x)        x = self.c2(x)        y = self.b2(x)        if self.residual_path:            residual = self.down_c1(inputs)            residual = self.down_b1(residual)        # 输出是两部分的和,即F(x)+x 或 F(x)+W(x),,再过激活函数        out = self.a2(y+ residual)        return out

代码实现——ResNet网络:

class ResNet18(Model):    # block_list 表示每层Block有几个卷积层    def __init__(self,block_list,initial_filters = 64):        super(ResNet18,self).__init__()        self.num_blocks = len(block_list)        self.block_list = block_list        self.out_filters = initial_filters        # 第一层卷积        self.c1 = Conv2D(self.out_filters,(3,3),strides = 1,padding = 'same',use_bias=False)        self.b1 = BatchNormalization()        self.a1 = Activation('relu')        # 第一个橙色块:两条实线【维度相同】        # 第二,第三,第四个橙色块:一条虚线+一条实线        # 构建ResNet块        self.blocks = tf.keras.models.Sequential()        # 循环次数由 block_list个数决定 为[2,2,2,2]        for block_id in range(len(block_list)):# 第几个restnet block            for layer_id in range(block_list[block_id]):# 第几个卷积层                # block=生成一个橙色块                 # 对除第一个block以外的每个block的输入进行下采样                if block_id != 0 and layer_id ==0:                    # residual 为T 虚线【维度不同,需处理】                    block = ResnetBlock(self.out_filters,strides=2,residual_path =True)                else:                    # residual 为T 虚线【维度不同,需处理】                    block = ResnetBlock(self.out_filters,residual_path = False)                self.blocks.add(block)# 构建好的block加入restnet            self.out_filters *= 2 # 下一个block的卷积核是上一个block的2倍        self.p1 = tf.keras.layers.GlobalAveragePooling2D()        self.f1 = tf.keras.layers.Dense(10,activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())    def call(self,inputs):        x = self.c1(inputs)        x = self.b1(x)        x = self.a1(x)        x = self.blocks(x)        x = self.p1(x)        y = self.f1(x)        return y

模型构成:

f7ea919825e745fe8691ef8519b540a4.png

训练过程:

da63246f7e8ab08171dae9a0d0edc1e4.png

实验结果:

fe30d96eba96230a280606d0e0319333.png

3.Inception和ResNet核心组成单元对比

实际上我们发现之前的三种网络是拿卷积层堆叠的,这个网络是拿ResNet块堆叠的,而ResNet块是拿卷积层堆叠加上残差跳连组成的,说起来差很多,但是好像也差不多。

78bdab6c61470a55096336d461903a71.png

4.五种经典卷积神经网络小结

08dc9b2eff6ab6a1b747a3dc55986208.png


小结:

          经典的5大卷积神经网络,是伴随一篇篇论文发展而来:卷积核共享,换激活函数,加上舍弃层,使用BN,使用小尺寸卷积核减少参数,自建模块实现想要的功能,提升感知力的每层使用不同尺寸卷积核,引入前方信息的残差跳连使得深度加深成为可能...

          后来还有很多基于这些经典神经网络的升级版本,如GoogLeNet 就是基于Inception发展而来,也有很多更新奇的点子和有趣的设计,他们能达到更好的效果,为游戏设计的GPU发展更加迅猛,计算能力大幅提升,一起学习其他的CNN吧。


5.神经网络搭建和CNN的有关文章:

推荐按顺序阅读

1.神经网络搭建:告诉我们如何按套路搭建神经网络模型。

TF2.0-神经网络模型搭建6步法,Sequential顺序神经网络结构,Class类搭建带连跳网络结构【含实践】

2.神经网络搭建:教会我们如何完成神经网络搭建的信息存储,模型存储,和可视化,也都是直接套用和有规律的。

TF2.0-应用数据模型的6种办法【自制数据集,数据增强扩充数据集,存取模型,参数提取,acc/loss可视化,应用实例】

3.CNN:明确卷积神经网络就是用来提取特征的,CBAPD模式=特征提取器,根据前两篇文章教会我们的来搭建一个糟糕的Baseline。

TF-2.0 卷积CBAPD特征提取器+六步法【卷积+BN+激活+丢弃+池化】实现Baseline基准神经网络cifar10分类

4.经典CNN的实现:通过复现经典CNN来强化搭建神经网络模型的思路。

TF2.0-自作图+代码实现:LeNet,AlexNet,VggNet,Inception经典神经网络         

5.本文      


基本搭建神经网络和CNN部分至此 

谢谢阅读!

(提取码:re9v)

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值