deeplabv3+源码之慢慢解析25 第四章network文件夹(6)utils.py--_SimpleSegmentationModel类和IntermediateLayerGetter类

系列文章目录(共五章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. utils.py是network文件夹里的最后一个文件,包含2个类:_SimpleSegmentationModel类(对骨干网络的导入)和IntermediateLayerGetter类(获取模型中间层的输出,可以是一层,也可以是多层)。

导入部分

import torch
import torch.nn as nn
import numpy as np
import torch.nn.functional as F #以上都是前文见过的常规导入。
from collections import OrderedDict #python字典本无序(即两个字典内容相同即相等),有序用这个(即两个字典即使内容相同,但顺序不同也不同),详见文后补充。

_SimpleSegmentationModel类

提示:hrnet骨干网络。

class _SimpleSegmentationModel(nn.Module):#对骨干网络的导入
    def __init__(self, backbone, classifier):
        super(_SimpleSegmentationModel, self).__init__()
        self.backbone = backbone
        self.classifier = classifier #设定好骨干网和分类器
        
    def forward(self, x):
        input_shape = x.shape[-2:] #输入数据一般为[batch_size,channels,h,w],取最后2个维度,即长和宽。
        features = self.backbone(x) #获得骨干网输出的feature-map输出。
        x = self.classifier(features) #对输出数据进行最后的分类。
        x = F.interpolate(x, size=input_shape, mode='bilinear', align_corners=False) #按input_shape进行插值调整结果数据,而后输出最终结果。
        return x

IntermediateLayerGetter类

提示: pytorch中本来就有IntermediateLayerGetter,获取模型中间层的输出,可以是一层,也可以是多层。
IntermediateLayerGetter的两个限制:
(1)在forward函数中不能对同一个模块使用两次
(2)只能调用一级子模块,不能调用二级以下的模块

class IntermediateLayerGetter(nn.ModuleDict):
    """
    Module wrapper that returns intermediate layers from a model

    It has a strong assumption that the modules have been registered
    into the model in the same order as they are used.
    This means that one should **not** reuse the same nn.Module
    twice in the forward if you want this to work.

    Additionally, it is only able to query submodules that are directly
    assigned to the model. So if `model` is passed, `model.feature1` can
    be returned, but not `model.feature1.layer2`.
    
    Arguments:
        model (nn.Module): model on which we will extract the features
        return_layers (Dict[name, new_name]): a dict containing the names
            of the modules for which the activations will be returned as
            the key of the dict, and the value of the dict is the name
            of the returned activation (which the user can specify).

    Examples::

        >>> m = torchvision.models.resnet18(pretrained=True)
        >>> # extract layer1 and layer3, giving as names `feat1` and feat2`
        >>> new_m = torchvision.models._utils.IntermediateLayerGetter(m,
        >>>     {'layer1': 'feat1', 'layer3': 'feat2'})
        >>> out = new_m(torch.rand(1, 3, 224, 224))
        >>> print([(k, v.shape) for k, v in out.items()])
        >>>     [('feat1', torch.Size([1, 64, 56, 56])),
        >>>      ('feat2', torch.Size([1, 256, 14, 14]))]
    """
    def __init__(self, model, return_layers, hrnet_flag=False): #return_layers就是返回这层(或者这几层)的输出。
        if not set(return_layers).issubset([name for name, _ in model.named_children()]):  #return_layers需要在model有名字的子层里,如果不符则报错。model.named_children()详见后补链接。
            raise ValueError("return_layers are not present in model")

        self.hrnet_flag = hrnet_flag #如果是hrnet骨干网,使用这个flag,这个骨干网需要单独处理网络结构的一些问题。

        orig_return_layers = return_layers
        return_layers = {k: v for k, v in return_layers.items()} #将return_layers从参数中分解开。
        layers = OrderedDict()  #定义排序的字典
        for name, module in model.named_children():
            layers[name] = module  #把原return_layers中的内容,重新放到排序字典layers中。
            if name in return_layers:
                del return_layers[name] #在layers中放一个,就在return_layers中删掉一个。
            if not return_layers:  #如果return_layers已经删空了,则break跳出循环。
                break

        super(IntermediateLayerGetter, self).__init__(layers) #按排序字典layers进行初始化构建对象。
        self.return_layers = orig_return_layers  #self.return_layers保持参数传进来的原return_layers值。

    def forward(self, x):
        out = OrderedDict() #定义排序字典out,输出使用。
        for name, module in self.named_children():
            if self.hrnet_flag and name.startswith('transition'): # if using hrnet, you need to take care of transition #如果是hrnet就需要对transition进行处理,transition详见hrnetv2.py。
                if name == 'transition1': # in transition1, you need to split the module to two streams first
                    x = [trans(x) for trans in module]
                else: # all other transition is just an extra one stream split
                    x.append(module(x[-1]))
            else: # other models (ex:resnet,mobilenet) are convolutions in series.
                x = module(x)

            if name in self.return_layers:
                out_name = self.return_layers[name]
                if name == 'stage4' and self.hrnet_flag: # In HRNetV2, we upsample and concat all outputs streams together #同上,使用hrnet需要进行处理,详见hrnetv2.py。
                    output_h, output_w = x[0].size(2), x[0].size(3)  # Upsample to size of highest resolution stream
                    x1 = F.interpolate(x[1], size=(output_h, output_w), mode='bilinear', align_corners=False)
                    x2 = F.interpolate(x[2], size=(output_h, output_w), mode='bilinear', align_corners=False)
                    x3 = F.interpolate(x[3], size=(output_h, output_w), mode='bilinear', align_corners=False)
                    x = torch.cat([x[0], x1, x2, x3], dim=1)
                    out[out_name] = x
                else:
                    out[out_name] = x  #使用其他骨干网络,则直接对应上面module(x)的输出x。
        return out

Tips

  1. 补充:python的有序字典
  2. 补充:IntermediateLayerGetter类
  3. 补充:关于pythorch中model各种module的说明
  4. utils.py代码就是对_deeplab.py(_SimpleSegmentationModel类)和modeling.py(IntermediateLayerGetter类)的补充,至于是否一定要放在单独的文件里,每个程序员的理解可能都不一样,不多解释。
  5. 至此,最关键的文件夹network已经完毕。
  6. 下一章开始,进入源码的最后一个文件夹utils。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值