我要彻底搞懂SSD网络结构(1)VGG部分

本问代码全部由大神Bubbliiiing的开源代码,使用pytorch版本的,并从各种地方寻找资料,主要是Bubbliiiing大兄弟的!

主干网络

VGG前两步

主干网络采用了VGG,直接上代码:

base = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'C', 512, 512, 512, 'M',
            512, 512, 512]

def vgg(i):
    layers = []
    in_channels = i
    for v in base:
        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)
            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

padding=1

padding有两种可选值:‘VALID’和‘SAME’。
取值为‘VALID’时padding=0,并不会对输入(input)做填充;
取值为‘SAME’时padding>0,将会对输入(input)做填充,填充值都是0值。
所以VGG网络中,卷积层padding=1,都对输入矩阵进行了周围都是0的填充,不难发现,前两次卷积过后,300×300×3的矩阵并没有发生变化,在base='M’之前,矩阵都是300×300×3 。

网络结构变化

这里,nn.Conv2d中的参数,

conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)

in_channels:输入的通道数,
v:输出的通道数,
kernel_size:卷积核的大小,
padding:采用’SAME’的方式对矩阵进行填充。
在这里插入图片描述
首先,300×300×3的输入后,第一次卷积将通道数由3变为了后来的64,卷积核大小为3×3,将输入的网络调整为300-3+1=298,但是由于padding对整个300×300的网络进行了0的填充,矩阵前后各自增加了0,所以具体的过程为:
(300+2)-3+1=300,矩阵经过卷积后大小没有发生变化!通道数增加为64!
两次卷积进行了相同的操作

最大池化层

最大池化比较好理解,就是在这2×2之中去出最大的来,经过最大池化层后,通道数没有发生任何变化,输入矩阵的大小由300变为了150,具体过程为:
(300-2+1)/2=149.5,最后向上取整=150 。
将以上的操作进行两遍,最后能够获得,75×75×128的矩阵。

VGG第三步

这里将矩阵变化为了38×38×256,但是遇到了新的base=‘C’,这里的C代表着ceil_mode=True,这里的主要含义为:
同样进行与之前的相同池化操作,但是我们保留了单数边的卷积信息。
刚刚我们遇到了将300×300×64转化为150×150×64,这里正好可以将偶数边完整的进行池化,但是如果遇到了奇数边,则会有一行一列的数据丢失,在这里75×75×128就遇到了这种情况,我们的ceil_mode可以为我们的矩阵最后的一边一列继续进行池化,最后我们的结果就会变为38×38×256

后面完全相同。

VGG循环中卷积最后一步

我们能够得到19×19×512的卷积结果。

VGG最后一步

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)]

pool5: 19×19×512 -> 19×19×512

conv6:19×19×512 -> 19×19×1024

conv7:19×19×1024 -> 19×19×1024

猜你喜欢

转载自blog.csdn.net/qq_43656233/article/details/107588402