deeplabv3+源码之慢慢解析15 第四章network文件夹(1)backbone文件夹(b1)mobilenetv2.py--2个函数和2个类

系列文章目录(更新中)

`
第一章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–[17个类]
第五章deeplabv3+源码之慢慢解析 utils文件夹(2)loss.py–[1个类]
第五章deeplabv3+源码之慢慢解析 utils文件夹(3)scheduler.py–[1个类]
第五章deeplabv3+源码之慢慢解析 utils文件夹(4)utils.py–[1个类,4个函数]
第五章deeplabv3+源码之慢慢解析 utils文件夹(5)visualizer.py–[1个类]
总结

文章目录

  • 系列文章目录(更新中)
    • 前期准备和说明
    • mobilenetv2.py的导入部分
    • mobilenetv2.py的非函数非类代码
    • 确保整除 _make_divisible函数
    • 基本结构块 ConvBNReLU类
    • 计算填充 fixed_padding函数
    • InvertedResidual类


前期准备和说明

  1. 上一个结构中提到的链接和补充,新手应该已经看完了,再来学习本节内容。
  2. 还是建议:有足够的耐心看完本章推荐的全部补充链接。
  3. 先看关于mobilenet和mobilenetV2的理论部分。(老规矩,看文后补充链接)。
  4. MobileNetV2中最主要的3特点: 整个结构按照维度来看,类似一个中间宽,两边窄的结构。整个过程是扩张(维度增加),卷积(长和宽降低),压缩(通道数减少)。)
    (1)Inverted Residuals (倒残差结构 )。详见InvertedResidual类。通常的residuals block是先经过一个1*1的Conv layer,把feature map的通道数“压”下来,再经过3*3 Conv layer,最后经过一个1*1 的Conv layer,将feature map 通道数再“扩张”回去。即先“压缩”,最后“扩张”回去。而 inverted residuals就是 先“扩张”,最后“压缩”。
    (2)Linear Bottlenecks(结构的最后一层采用线性层)。详见MobileNetV2类。Linear bottlenecks,为了避免Relu对特征的破坏,在residual block的Eltwise sum之前的那个 1*1 Conv 不再采用Relu。
    (3)在MobileNet结构中,采用了新的激活函数:ReLU6(x)=min(max(0,x),6)。见ConvBNReLU类。

mobilenetv2.py的导入部分

#还是简简单单,torch的各种基本功能
from torch import nn
try: # for torchvision<0.4
    from torchvision.models.utils import load_state_dict_from_url
except: # for torchvision>=0.4
    from torch.hub import load_state_dict_from_url
import torch.nn.functional as F

mobilenetv2.py的非函数非类代码

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

__all__ = ['MobileNetV2', 'mobilenet_v2']  #MobileNetV2类, mobilenet_v2函数。

model_urls = {
    'mobilenet_v2': 'https://download.pytorch.org/models/mobilenet_v2-b0353104.pth', #预训练模型下载地址。
}


确保整除 _make_divisible函数

def _make_divisible(v, divisor, min_value=None):
    """
    This function is taken from the original tf repo.
    It ensures that all layers have a channel number that is divisible by 8
    It can be seen here:
    https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
    :param v:
    :param divisor:
    :param min_value:  #此函数中要注意,如果保证结果是divisor的整数倍,则min_value最好用默认值,否则可能出现意外,如_make_divisible(5,8,31)==31。
    :return:
    """
    if min_value is None:
        min_value = divisor
    new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) #//是商取整数部分的运算符,此处即int(v + divisor / 2) // divisor再* divisor,得到的就是divisor的整数倍。divisor==8就是8的整数倍。
    # Make sure that round down does not go down by more than 10%.
    if new_v < 0.9 * v:    #如果小于v的90%,则加一个divisor,相当于加了1倍。
        new_v += divisor
    return new_v

基本结构块 ConvBNReLU类

提示:基本结构块Conv2d+BatchNorm2d+ReLU6,在InvertedResidual类和MobileNetV2类中使用。

class ConvBNReLU(nn.Sequential):
    def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, dilation=1, groups=1):
        #padding = (kernel_size - 1) // 2
        super(ConvBNReLU, self).__init__(
            nn.Conv2d(in_planes, out_planes, kernel_size, stride, 0, dilation=dilation, groups=groups, bias=False),
            nn.BatchNorm2d(out_planes),
            nn.ReLU6(inplace=True)   #基本序列Conv2d+BatchNorm2d+ReLU6。
        )

计算填充 fixed_padding函数

def fixed_padding(kernel_size, dilation): #特别注意:在Pytorch中,空洞卷积(膨胀卷积)dilation = 1等同于没有dilation的标准卷积。dilation = 2才是间隔1个,扩大感受野。
    kernel_size_effective = kernel_size + (kernel_size - 1) * (dilation - 1) #插入空洞后,新的卷积核尺寸。
    pad_total = kernel_size_effective - 1 #在保持高和宽不变的情况下,卷积减少的尺寸为k-1,有padding填充的为2p,即k-1=2p。则p=(k-1)//2。
    pad_beg = pad_total // 2
    pad_end = pad_total - pad_beg
    return (pad_beg, pad_end, pad_beg, pad_end) 

InvertedResidual类

class InvertedResidual(nn.Module): #论文中把这个整体叫做bottleneck。
    def __init__(self, inp, oup, stride, dilation, expand_ratio):
        super(InvertedResidual, self).__init__()
        self.stride = stride
        assert stride in [1, 2] #测试用,stride=1则分辨率不变,stride=2则分辨率降一半。

        hidden_dim = int(round(inp * expand_ratio)) #输入*扩展系数=hidden_dim ,即中间的输出数量。
        self.use_res_connect = self.stride == 1 and inp == oup #stride==1且输入输出数量相等,则use_res_connect=True。

        layers = []
        if expand_ratio != 1:#如果扩展系数不为1,即需要扩大中间的输出通道数,则进行kernel=1的升维。即论文中的前期的pw升维部分。
            # pw
            layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1))

        layers.extend([
            # dw
            ConvBNReLU(hidden_dim, hidden_dim, stride=stride, dilation=dilation, groups=hidden_dim),#正常的DW部分。
            # pw-linear #pw线性降维部分,不用激活函数。
            nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
            nn.BatchNorm2d(oup),
        ])
        self.conv = nn.Sequential(*layers) #整合网络各层,即pw+dw+pw-linear,论文中把这个整体叫做bottleneck,本代码没有单独写出这个名字。

        self.input_padding = fixed_padding( 3, dilation )#计算填充的尺寸。

    def forward(self, x):
        x_pad = F.pad(x, self.input_padding) #把输入x按填充尺寸填充。
        if self.use_res_connect: #特别的,针对stride=1 和stride=2,在block上有稍微不同,主要是为了与shortcut的维度匹配,因此,stride=2时,不采用shortcut。 
            return x + self.conv(x_pad) #stride==1且输入输出数量相等时,输入x与输出结果整合。
        else:
            return self.conv(x_pad)

Tips

  1. 补充:mobilenet V2原文。
  2. 补充:mobilenet,mobilenet V2。
  3. 补充:mobilenet,mobilenet V2,Resnet对比。
  4. 补充:dalition详解,padding,stride,dalition关系。
  5. 每个骨干网的第一节,重在看原理,其次是部分代码。
  6. 下一节是mobilenetv2.py剩余的部分,即MobileNetV2类和mobilenet_v2函数。

你可能感兴趣的:(技术,人工智能,deeplab,v3+,语义分割,深度学习)