您的位置:首页 > 理论基础 > 计算机网络

SSD原理及Pytorch代码解读——网络架构(一):基础结构

2020-07-24 16:15 483 查看

基础VGG结构

SSD采用VGG16作为基础网络,并在其基础上做了一些改动,如下图所示。输入图像经过预处理后大小固定为300×300,首先经过VGG16网络的前13个卷积层,然后利用两个卷积Conv 6与Conv 7取代了原来的全连接网络,进一步提取特征。
与原来的VGG16的网络结构相比,主要的改动在这三个方面:

  1. 使用两个卷积模块Conv 6与Conv 7取代了原来的全连接网络。
  2. 原始的VGG 16的池化层统一大小为2×2,步长为2(这样设计使得特征图经过conv层不改变特征图的尺寸,经过pool层特征图尺寸会缩小到原来的一半),而在SSD中,Conv 5后接的Maxpooling层池化大小为3,步长为1,这样做可以在增加感受野的同时,维持特征图的尺寸不变。
  3. Conv 6中使用了空洞数为6的空洞卷积,其padding也为6,这样做同样也是为了增加感受野的同时保持参数量与特征图尺寸的不变。

深度卷积层

在VGG 16的基础上,SSD进一步增加了4个深度卷积层,用于更高语义信息的提取,如下图所示。可以看出,Conv 8的通道数为512,而Conv 9、Conv 10与Conv 11的通道数都为256。从Conv 7到Conv 11,这5个卷积后输出特征图的尺寸依次为19×19、10×10、5×5、3×3和1×1。
为了降低参数量,在此使用了1×1卷积先降低通道数为该层输出通道数的一半,再利用3×3卷积进行特征提取。

整个SSD的网络结构图如下(特征图尺寸以通道优先模式表示):

源码

SSD的基础网络代码主要在ssd.py中,具体如下:

基础VGG结构

# 这里的base为VGG-16前13个卷积层构造,M代表maxpooling,C代表ceil_mode为True, 数字是ConV2d的输出通道数
base = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'C', 512, 512, 512, 'M',
512, 512, 512]

def vgg(cfg, i, batch_norm=False):
"""
建立VGG基础结构
parameter:
cfg:每一层的结构信息,即base列表
i: 初始通道数
batch_norm:是否接上BN层
return:
layers:vgg基础结构列表
"""
layers = []
in_channels = i
for v in cfg:
if v == 'M':
layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
elif v == 'C':
layers += [nn.MaxPool2d(kernel_size=2, stride=2, ceil_mode=True)]
else:
conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
if batch_norm:
layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)]
else:
layers += [conv2d, nn.ReLU(inplace=True)]
in_channels = v
pool5 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
conv6 = nn.Conv2d(512, 1024, kernel_size=3, padding=6, dilation=6)
conv7 = nn.Conv2d(1024, 1024, kernel_size=1)
layers += [pool5, conv6,
nn.ReLU(inplace=True), conv7, nn.ReLU(inplace=True)]
return layers

深度卷积层

# 额外部分的卷积通道数,S代表了步长为2,其余卷积层默认步长为1, 数字是ConV2d的输出通道数
extras = [256, 'S', 512, 128, 'S', 256, 128, 256, 128, 256]

# 额外的深度卷积层构造函数
def add_extras(cfg, i, batch_norm=False):
"""
建立VGG基础结构
parameter:
cfg:每一层的结构信息,即extras列表
i: 初始通道数
batch_norm:是否接上BN层
return:
layers:深度卷积层结构列表
"""
layers = []
in_channels = i
flag = False
for k, v in enumerate(cfg):
if in_channels != 'S':
if v == 'S':
layers += [nn.Conv2d(in_channels, cfg[k + 1],
kernel_size=(1, 3)[flag], stride=2, padding=1)]
else:
layers += [nn.Conv2d(in_channels, v, kernel_size=(1, 3)[flag])]
flag = not flag
in_channels = v
return layers
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: