第一章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个类]
总结
import torch
import torch.nn as nn
import numpy as np
import torch.nn.functional as F #以上都是前文见过的常规导入。
from collections import OrderedDict #python字典本无序(即两个字典内容相同即相等),有序用这个(即两个字典即使内容相同,但顺序不同也不同),详见文后补充。
提示: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
提示: 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