deeplabv3+源码之慢慢解析19 第四章network文件夹(1)backbone文件夹(d1)xception.py--SeparableConv2d类和Block类

系列文章目录(共五章33节已完结)

第一章deeplabv3+源码之慢慢解析 根目录(1)main.py–get_argparser函数
第一章deeplabv3+源码之慢慢解析 根目录(2)main.py–get_dataset函数
第一章deeplabv3+源码之慢慢解析 根目录(3)main.py–validate函数
第一章deeplabv3+源码之慢慢解析 根目录(4)main.py–main函数
第一章deeplabv3+源码之慢慢解析 根目录(5)predict.py–get_argparser函数和main函数

第二章deeplabv3+源码之慢慢解析 datasets文件夹(1)voc.py–voc_cmap函数和download_extract函数
第二章deeplabv3+源码之慢慢解析 datasets文件夹(2)voc.py–VOCSegmentation类
第二章deeplabv3+源码之慢慢解析 datasets文件夹(3)cityscapes.py–Cityscapes类
第二章deeplabv3+源码之慢慢解析 datasets文件夹(4)utils.py–6个小函数

第三章deeplabv3+源码之慢慢解析 metrics文件夹stream_metrics.py–StreamSegMetrics类和AverageMeter类

第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a1)hrnetv2.py–4个函数和可执行代码
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a2)hrnetv2.py–Bottleneck类和BasicBlock类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a3)hrnetv2.py–StageModule类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a4)hrnetv2.py–HRNet类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(b1)mobilenetv2.py–2个类和2个函数
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(b2)mobilenetv2.py–MobileNetV2类和mobilenet_v2函数
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(c1)resnet.py–2个基础函数,BasicBlock类和Bottleneck类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(c2)resnet.py–ResNet类和10个不同结构的调用函数
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(d1)xception.py–SeparableConv2d类和Block类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(d2)xception.py–Xception类和xception函数
第四章deeplabv3+源码之慢慢解析 network文件夹(2)_deeplab.py–ASPP相关的4个类和1个函数
第四章deeplabv3+源码之慢慢解析 network文件夹(3)_deeplab.py–DeepLabV3类,DeepLabHeadV3Plus类和DeepLabHead类
第四章deeplabv3+源码之慢慢解析 network文件夹(4)modeling.py–5个私有函数(4个骨干网,1个模型载入)
第四章deeplabv3+源码之慢慢解析 network文件夹(5)modeling.py–12个调用函数
第四章deeplabv3+源码之慢慢解析 network文件夹(6)utils.py–_SimpleSegmentationModel类和IntermediateLayerGetter类

第五章deeplabv3+源码之慢慢解析 utils文件夹(1)ext_transforms.py.py–2个翻转类和ExtCompose类
第五章deeplabv3+源码之慢慢解析 utils文件夹(2)ext_transforms.py.py–2个裁剪类和2个缩放类
第五章deeplabv3+源码之慢慢解析 utils文件夹(3)ext_transforms.py.py–旋转类,填充类,张量转化类和标准化类
第五章deeplabv3+源码之慢慢解析 utils文件夹(4)ext_transforms.py.py–ExtResize类,ExtColorJitter类,Lambda类和Compose类
第五章deeplabv3+源码之慢慢解析 utils文件夹(5)loss.py–FocalLoss类
第五章deeplabv3+源码之慢慢解析 utils文件夹(6)scheduler.py–PolyLR类
第五章deeplabv3+源码之慢慢解析 utils文件夹(7)utils.py–去标准化,momentum设定,标准化层锁定和路径创建
第五章deeplabv3+源码之慢慢解析 utils文件夹(8)visualizer.py–Visualizer类(完结)


前期准备和说明

  1. 还是建议:有足够的耐心看完本章推荐的全部补充链接。
  2. 虽然在mobilenet中说过深度可分离卷积,但形象不深的同学还是建议再看看理论部分。(老规矩,看文后补充链接)。
  3. Xception是Inception的改进版,Inception v1就是当年的GoogleNet。Xception在Inception的基础上,使用深度可分离卷积(depthwise separate convolution)替代传统的Inception块,实现跨通道相关性和空间相关性的完全解耦。此外,还引入了残差连接,最终提出了Xception的网络结构。
    深度可分离卷积主要分为两个过程:
    (1)逐通道卷积(Depthwise Convolution, DW)。其中一个通道只被一个卷积核卷积,输入和输出通道数不变。简单来说,DW就是单通道卷积计算,目的在于降低参数数量。
    (2)逐点卷积(Pointwise Convolution, PW)。这个部分与常规卷积运算非常相似,卷积核的尺寸为 1×1×M,M为上一层的通道数。简单来说就是改变通道数的操作。在各种网络的改进中,PW如果放在DW后面,就是整合各个通道的信息;如果放在DW前面就是为了改变通道数(即升维或者降维)。
    Xception的具体结构:共包括36层卷积,分为14个stage。
    (1)Entry flow:stage1(2卷积),stage2(2分离卷积),stage3(2分离卷积),stage4(2分离卷积)。
    (2)Middle flow:stage5-12,同一stage循环8次(3分离卷积)。
    (3)Exit flow:stage13(2分离卷积),stage14(2分离卷积)。

xception.py的导入部分


from __future__ import print_function, division, absolute_import #__future__模块是为了在当前版本python中使用新python3.x特性而加入的语法。
import math
import torch #还是简简单单,torch的各种基本功能
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.model_zoo as model_zoo
from torch.nn import init

xception.py的非函数非类代码

提示:提示:xception.py包含1个函数和3个类。先介绍非函数非类的代码。

__all__ = ['xception']  #xception函数

pretrained_settings = {  #预训练模型设置
    'xception': {
        'imagenet': {
            'url': 'http://data.lip6.fr/cadene/pretrainedmodels/xception-43020ad28.pth',
            'input_space': 'RGB',
            'input_size': [3, 299, 299],
            'input_range': [0, 1],
            'mean': [0.5, 0.5, 0.5],
            'std': [0.5, 0.5, 0.5],
            'num_classes': 1000,
            'scale': 0.8975 # The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299
        }
    }
}


SeparableConv2d类

提示:即DW+PW阶段。

class SeparableConv2d(nn.Module):
    def __init__(self,in_channels,out_channels,kernel_size=1,stride=1,padding=0,dilation=1,bias=False):
        super(SeparableConv2d,self).__init__()

        self.conv1 = nn.Conv2d(in_channels,in_channels,kernel_size,stride,padding,dilation,groups=in_channels,bias=bias) #通道数不变的DW卷积。
        self.pointwise = nn.Conv2d(in_channels,out_channels,1,1,0,1,1,bias=bias) #改变通道数的PW卷积。

    def forward(self,x):
        x = self.conv1(x)#DW
        x = self.pointwise(x)#PW
        return x

Block类

提示:基础块,实际上就是:分离卷积层+relu+池化层。如果按stage分的话,输入和输出各算1个stage,下面的块,每一个块算一个stage。
(1)Entry flow:输入stage+3个块(2个(relu(第一个块没有relu)+分离卷积)+maxpooling)。
(2)Middle flow:循环8个块(3个(relu+分离卷积),无池化)。
(3)Exit flow:2个块(2个(relu+分离卷积)+maxpooling)+输出stage。

class Block(nn.Module):#此块是指原文中的ReLU+3*3SeparableConv2d的小组合。主要参数即是否以relu开头start_with_relu,是否是这个部分的第一个小组合grow_first。
    def __init__(self,in_filters,out_filters,reps,strides=1,start_with_relu=True,grow_first=True, dilation=1):
        super(Block, self).__init__()
		#filters过滤器的个数就是卷积核的组数,实际上对应的就是输出通道的个数。后补链接,新手同学建议看看。
        if out_filters != in_filters or strides!=1: #通道数量变化或者尺寸变化时
            self.skip = nn.Conv2d(in_filters,out_filters,1,stride=strides, bias=False)#此处的skip connection(跳连)其实就是之前提到过的shorcut(中文译为捷径比较合适),就是如果无变化则与输入相加,如果变化了则把输入进行这个层的操作再相加。
            self.skipbn = nn.BatchNorm2d(out_filters)#标准化。
        else:
            self.skip=None #无变化则不需要这个处理,后面直接使用输入数据即可。

        rep=[] #别的主干网,往往用layers=[]这个写法,就是重复的层。

        filters=in_filters #先按输入通道设置卷积核数量
        if grow_first: #关于参数grow_first,从程序看,先增长,即在第一个分离卷积层把输出通道增大为out_filters的意思。而如果值为false,即在最后一个分离卷积层再把输出通道增大为out_filters。
            rep.append(nn.ReLU(inplace=True)) #inplace = True ,会改变输入数据的值,节省反复申请与释放内存的空间与时间。inplace = False 时,不会修改输入对象的值,而是返回一个新创建的对象。
            rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=dilation, dilation=dilation, bias=False)) #第一个分离卷积,通道数对应in_filters和out_filters。
            rep.append(nn.BatchNorm2d(out_filters))
            filters = out_filters #第一个小组合之后,对应的输入通道数就是第一次的输出通道数,即out_filters。

        for i in range(reps-1):  #第1个小组合后,按循环次数reps,再加入reps-1个小组合,输入和输出通道数为out_filters。如果grow_first=False,则先按输入和输出通道数为in_filters做reps-1个小组合,后面的代码再接一个out_filters的输出小组合。
            rep.append(nn.ReLU(inplace=True))
            rep.append(SeparableConv2d(filters,filters,3,stride=1,padding=dilation,dilation=dilation,bias=False))
            rep.append(nn.BatchNorm2d(filters))

        if not grow_first:  #如果grow_first=False,最后接一个通道数为in_filters和out_filters的分离卷积层。
            rep.append(nn.ReLU(inplace=True))
            rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=dilation,dilation=dilation,bias=False))
            rep.append(nn.BatchNorm2d(out_filters))

        if not start_with_relu:
            rep = rep[1:]  #去掉第一个relu层。
        else:
            rep[0] = nn.ReLU(inplace=False) #第一个relu层,inplace=False不改变输入数据。

        if strides != 1: 
            rep.append(nn.MaxPool2d(3,strides,1)) #如改变尺寸,按原文strides=2,则块的最后加入3*3的MaxPooling。
        self.rep = nn.Sequential(*rep)

    def forward(self,inp):
        x = self.rep(inp)  #inp就是输入数据。

        if self.skip is not None:
            skip = self.skip(inp)  #如skip不为空则按这个shortcut进行相加。
            skip = self.skipbn(skip)
        else:
            skip = inp #如skip为空则直接按input进行相加。
        x+=skip 
        return x

Tips

  1. 补充:深度可分离卷积
  2. 补充:Xception理论
  3. 补充:卷积中的filters
  4. 下一节是xception.py剩余的部分,即Xception类和xception函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值