第一章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个类]
总结
#还是简简单单,torch的各种基本功能
import torch
import torch.nn as 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
提示:提示:resnet.py包含12个函数和3个类。先介绍非函数非类的代码。
__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',
'resnet152', 'resnext50_32x4d', 'resnext101_32x8d',
'wide_resnet50_2', 'wide_resnet101_2'] #可供使用的类和不同结构所用的函数。
model_urls = { #各预训练模型下载的地址。
'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth',
'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth',
'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth',
'wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth',
}
ResNet中两种不同的residual(不同的ResNet层数结构使用不同的residual): BasicBlock(即两个33conv+一个独立的shortcut)和 Bottleneck(即1个(11conv(降维)+33conv+11conv(升维))+一个独立的shortcut)。
而shortcut也分为两种,一是维度不变时,直接使用当前输入作为shortcut和conv块结果相加。二是维度变化时,通过1×1的卷积核进行了维度处理(特征矩阵在长宽方向降采样(常用strdie=2长宽减半),深度方向调整成下一层残差结构所需要的channel)。
def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
"""3x3 convolution with padding""" #使用3*3卷积核的卷积层
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
padding=dilation, groups=groups, bias=False, dilation=dilation)#此处的groups就是分组卷积。
def conv1x1(in_planes, out_planes, stride=1):
"""1x1 convolution""" #使用1*1卷积核的卷积层
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
提示:即两个3*3conv+一个独立的shortcut。
class BasicBlock(nn.Module):
expansion = 1 #扩展倍数。
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
base_width=64, dilation=1, norm_layer=None): #base_width是给wide_resnet使用的参数,普通resnet不用。
super(BasicBlock, self).__init__()
if norm_layer is None:
norm_layer = nn.BatchNorm2d
if groups != 1 or base_width != 64: #BasicBlock有很多不支持。
raise ValueError('BasicBlock only supports groups=1 and base_width=64')
if dilation > 1:
raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
# Both self.conv1 and self.downsample layers downsample the input when stride != 1
self.conv1 = conv3x3(inplanes, planes, stride)
self.bn1 = norm_layer(planes)
self.relu = nn.ReLU(inplace=True) #第一个3*3conv。
self.conv2 = conv3x3(planes, planes)
self.bn2 = norm_layer(planes) #第二个3*3conv。
self.downsample = downsample #传入的shortcut,默认无,即直接使用当前输入数据。
self.stride = stride
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out) #第一个3*3conv。
out = self.conv2(out)
out = self.bn2(out) #第二个3*3conv。
if self.downsample is not None:
identity = self.downsample(x) #传入的shortcut,详情在Resnet类中downsample。
out += identity #整合两个covnv层的输出和shortcut。
out = self.relu(out) #激活函数。
return out
提示:即1个(11conv(降维)+33conv+1*1conv(升维))+一个独立的shortcut。
class Bottleneck(nn.Module):
expansion = 4 #扩展倍数=4
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
base_width=64, dilation=1, norm_layer=None): #base_width是给wide_resnet和ResNeXt使用的参数,普通resnet不用。
super(Bottleneck, self).__init__()
if norm_layer is None:
norm_layer = nn.BatchNorm2d
width = int(planes * (base_width / 64.)) * groups #ResNet中其实就是width=planes。主要是ResNeXt使用的参数,分组卷积groups,这句中就是将通道数扩张了groups倍。base_width对应每个group的卷积核个数,即每个分组中的输出通道数。分母中的64是为了和ResNet类中self.layer1 = self._make_layer(block, 64, layers[0])保持一致。
# Both self.conv2 and self.downsample layers downsample the input when stride != 1
self.conv1 = conv1x1(inplanes, width)
self.bn1 = norm_layer(width) #第一个部分,1*1conv(降维),注width要比inplanes小才是降维。ResNeXt中不是降维。
self.conv2 = conv3x3(width, width, stride, groups, dilation) #分组卷积groups
self.bn2 = norm_layer(width) #第二个部分,3*3conv。
self.conv3 = conv1x1(width, planes * self.expansion)
self.bn3 = norm_layer(planes * self.expansion) #第三个部分,1*1conv(升维),将通道扩大expansion倍。此处为了和shortcut部分相加,通常是升维回到inplanes的大小。
self.relu = nn.ReLU(inplace=True) #激活函数
self.downsample = downsample #传入的shortcut,默认无,即直接使用当前输入数据。
self.stride = stride
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out) #第一个部分,1*1conv(降维)。
out = self.conv2(out)
out = self.bn2(out)
out = self.relu(out) #第二个部分,3*3conv。
out = self.conv3(out)
out = self.bn3(out) #第三个部分,1*1conv(升维)。
if self.downsample is not None:
identity = self.downsample(x) #传入的shortcut,详情在Resnet类中downsample。
out += identity #整合两个covnv层的输出和shortcut。
out = self.relu(out) #激活函数。
return out
Tips