deeplabv3+源码之慢慢解析20 第四章network文件夹(1)backbone文件夹(d2)xception.py--Xception类和xception函数

系列文章目录(共五章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类(完结)


Xception类


提示:Xception类是xception.py中的核心,整合各个功能。

class Xception(nn.Module):
    """
    Xception optimized for the ImageNet dataset, as specified in
    https://arxiv.org/pdf/1610.02357.pdf
    """
    def __init__(self, num_classes=1000, replace_stride_with_dilation=None):
        """ Constructor
        Args:
            num_classes: number of classes
        """
        super(Xception, self).__init__()

        self.num_classes = num_classes
        self.dilation = 1
        if replace_stride_with_dilation is None:
            # each element in the tuple indicates if we should replace
            # the 2x2 stride with a dilated convolution instead
            replace_stride_with_dilation = [False, False, False, False]
        if len(replace_stride_with_dilation) != 4:
            raise ValueError("replace_stride_with_dilation should be None "
                             "or a 4-element tuple, got {}".format(replace_stride_with_dilation))

        self.conv1 = nn.Conv2d(3, 32, 3,2, 0, bias=False) # 1 / 2#此处strde=2,长宽减半,基本的数据处理。把它理解为stage1的开始。
        self.bn1 = nn.BatchNorm2d(32)
        self.relu1 = nn.ReLU(inplace=True)

        self.conv2 = nn.Conv2d(32,64,3,bias=False)
        self.bn2 = nn.BatchNorm2d(64)
        self.relu2 = nn.ReLU(inplace=True)  #还是基本卷积,stage1的结束。
        #do relu here
 		#Entry Flow就是stage1-4
        self.block1=self._make_block(64,128,2,2,start_with_relu=False,grow_first=True, dilate=replace_stride_with_dilation[0]) # 1 / 4 #stage2,唯一的start_with_relu=False
        self.block2=self._make_block(128,256,2,2,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[1]) # 1 / 8 #stage3
        self.block3=self._make_block(256,728,2,2,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2]) # 1 / 16 #stage4
        
		#Middle Flow就是stage5-12,对应8个block的循环,即此处的block4-11,此处stride=1,没有maxpooling。
        self.block4=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
        self.block5=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
        self.block6=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
        self.block7=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])

        self.block8=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
        self.block9=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
        self.block10=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
        self.block11=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
		#Exit Flow就是stage13-14
        self.block12=self._make_block(728,1024,2,2,start_with_relu=True,grow_first=False, dilate=replace_stride_with_dilation[3]) # 1 / 32 #stage13,唯一的grow_first=False
 		#stage14,原文的stage14=2个深度卷积层+全局平均池化层+全连接层。此代码的实现方式,在最后有点绕。
        self.conv3 = SeparableConv2d(1024,1536,3,1,1, dilation=self.dilation) #stage14的深度卷积层1
        self.bn3 = nn.BatchNorm2d(1536)
        self.relu3 = nn.ReLU(inplace=True)

        #do relu here #从这个注释看,这个代码的作者也对他引用的原码中不足提出了意见。
        self.conv4 = SeparableConv2d(1536,2048,3,1,1, dilation=self.dilation)#stage14的深度卷积层2
        self.bn4 = nn.BatchNorm2d(2048)
 		#self.relu4 = nn.ReLU(inplace=True) #本文自行补充的,按原论文此处应该补一个relu。
        self.fc = nn.Linear(2048, num_classes) #stage14的全连接层

        # #------- init weights --------  #权重初始化
        # for m in self.modules():
        #     if isinstance(m, nn.Conv2d):
        #         n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
        #         m.weight.data.normal_(0, math.sqrt(2. / n))
        #     elif isinstance(m, nn.BatchNorm2d):
        #         m.weight.data.fill_(1)
        #         m.bias.data.zero_()
        # #-----------------------------

    def _make_block(self, in_filters,out_filters,reps,strides=1,start_with_relu=True,grow_first=True, dilate=False):
        if dilate: #是否使用空洞卷积代替strides
            self.dilation *= strides
            strides = 1
        return Block(in_filters,out_filters,reps,strides,start_with_relu=start_with_relu,grow_first=grow_first, dilation=self.dilation)

    def features(self, input):
        x = self.conv1(input)
        x = self.bn1(x)
        x = self.relu1(x)

        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu2(x) #以上为stage1

        x = self.block1(x)#stage2
        x = self.block2(x)#stage3
        x = self.block3(x)#stage4 以上为Entry flow
        x = self.block4(x)
        x = self.block5(x)
        x = self.block6(x)
        x = self.block7(x)
        x = self.block8(x)
        x = self.block9(x)
        x = self.block10(x)
        x = self.block11(x)#以上是Middle Flow,stage5-12,即此处的block4-11。
        x = self.block12(x)#stage13.以下是Exit Flow。

        x = self.conv3(x)#stage14,2个深度卷积层+全局平均池化层+全连接层。
        x = self.bn3(x)
        x = self.relu3(x) #stage14的深度卷积层1

        x = self.conv4(x) #stage14的深度卷积层2
        x = self.bn4(x)
        #x = self.relu4(x) #本文自补,应该有这个relu。这段代码把此处的relu放在了logits函数的开头,不贴和原文的‘深度卷积+relu’结构的表达,不建议这样写。
        return x

    def logits(self, features):
        x = nn.ReLU(inplace=True)(features)#这个relu应该写在stage14的深度卷积层2的后面。建议在上面函数增加self.relu4。此句可以注释掉。

        x = F.adaptive_avg_pool2d(x, (1, 1))#stage14的全局平均池化层
        x = x.view(x.size(0), -1)#扁平化处理,view(h,w),h代表行(想要变为几行),w代表的是列(想要变为几列)。当确定h行,却不知道几列时,则w=-1,自动按行计算列。
        x = self.last_linear(x)#stage14的全局平均池化层。如果一定这么写的话,其实直接用self.fc即可。
        return x

    def forward(self, input):
        x = self.features(input) #此处用self.features+self.logits连接了,感觉太绕了。
        x = self.logits(x)
        return x

本节建议的修改

提示:如果是我,可能这样写,features+logits+forward变为下面的forward。

    def forward(self, input):
        x = self.conv1(input)
        x = self.bn1(x)
        x = self.relu1(x)

        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu2(x) #以上为stage1

        x = self.block1(x) #stage2
        x = self.block2(x) #stage3
        x = self.block3(x) #stage4 以上为Entry flow
        x = self.block4(x) 
        x = self.block5(x)
        x = self.block6(x)
        x = self.block7(x)
        x = self.block8(x)
        x = self.block9(x)
        x = self.block10(x)
        x = self.block11(x)#以上是Middle Flow,stage5-12,即此处的block4-11。
        x = self.block12(x) #stage13.以下是Exit Flow。

        x = self.conv3(x)  #stage14,2个深度卷积层+全局平均池化层+全连接层+逻辑回归。
        x = self.bn3(x) #stage14的深度卷积层1
        x = self.relu3(x)

        x = self.conv4(x) #stage14的深度卷积层2
        x = self.bn4(x)
        x = self.relu4(x) #在__init__函数里,去掉self.relu4的注释。
        
        x = F.adaptive_avg_pool2d(x, (1, 1)) #stage14的全局平均池化层
        x = x.view(x.size(0), -1)  
        x = self.fc(x)
        return x

xception函数

def xception(num_classes=1000, pretrained='imagenet', replace_stride_with_dilation=None):
    model = Xception(num_classes=num_classes, replace_stride_with_dilation=replace_stride_with_dilation)#新建Xception模型
    if pretrained: #使用预训练则导入参数
        settings = pretrained_settings['xception'][pretrained]
        assert num_classes == settings['num_classes'], \
            "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)

        model = Xception(num_classes=num_classes, replace_stride_with_dilation=replace_stride_with_dilation)
        model.load_state_dict(model_zoo.load_url(settings['url']))#载入模型

    # TODO: ugly #哈哈,这个注释言简意赅,同感。
    model.last_linear = model.fc #补了forward函数中self.last_linear没有对应self.fc的硬伤
    del model.fc #补完之后,再应删掉self.fc,保持使用self.last_linear。确实ugly。
    return model

Tips

  1. 至此,xception.py结束。
  2. 通过各个主干网络的学习和对比,大家应该会发现,本代码中的主干网络大体结构类似,块结构中都有DW和PW,shortcut等。通道数和分辨率如天下大势,分分合合。
  3. 下一节回到了network文件夹下,讲一下_deeplab.py文件(终于看到deeplab字样了)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值