VGG原文:Very deep convolutional networks for large-scale image recognition:https://arxiv.org/pdf/1409.1556.pdf

VGG在2014年由牛津大学Visual GeometryGroup提出,获得该年lmageNet竞赛中Localization Task(定位任务)第一名和 Classification Task (分类任务)第二名。
VGG与AlexNet相比,它采用几个连续的3x3的卷积核代替AlexNet中的较大卷积核。
在VGG中,使用了3个3x3卷积核来代替7x7卷积核,使用了2个3x3卷积核来代替5*5卷积核,从而在保证具有相同感知野的条件下,提升了网络的深度,在一定程度上提升了神经网络的效果。

在论文中,作者尝试了使用5种不同的网络结构,深度分别为11,11,13,16,19,5种结构图如下所示:

其中最常用的是VGG16和VGG19,下面我们就以VGG16为例来分析它的网络结构。
VGG16中的16指的是它由16层组成(13个卷积层 + 3个全连接层,不包括池化层)。
VGG的输入图像大小为224X224X3的三通道彩色图像,共有1000个类别。

其中卷积层的卷积核大小都为3,padding为1;池化层的kernel_size为2,stride为2。
因此
VGG具有明显的块结构,VGG可以分为如下六块:
为了便于理解,我们把正向传播过程分为两块,
def make_features(self):
cfgs = [64, 64, 'MaxPool', 128, 128, 'MaxPool', 256, 256, 256, 'MaxPool', 512, 512, 512, 'MaxPool', 512, 512, 512, 'MaxPool']
layers = []
in_channel = 3
for cfg in cfgs:
if cfg == "MaxPool": # 池化层
layers += [nn.MaxPool2d(kernel_size=2,stride=2)]
else:
layers += [nn.Conv2d(in_channels=in_channel,out_channels=cfg,kernel_size=3,padding=1)]
layers += [nn.ReLU(True)]
in_channel = cfg
return nn.Sequential(*layers)
【注意】:在进行全连接之前,需要现将卷积层输出的三维特征图展平为1维。
x = torch.flatten(x,start_dim=1)
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(4096, 1000)
)
"""
#-*-coding:utf-8-*-
# @author: wangyu a beginner programmer, striving to be the strongest.
# @date: 2022/7/1 15:01
"""
import torch
import torch.nn as nn
class VGG(nn.Module):
def __init__(self):
super(VGG, self).__init__()
self.features = self.make_features()
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(4096, 1000)
)
def forward(self,x):
x = self.features(x)
x = torch.flatten(x,start_dim=1)
x = self.classifier(x)
return x
def make_features(self):
cfgs = [64, 64, 'MaxPool', 128, 128, 'MaxPool', 256, 256, 256, 'MaxPool', 512, 512, 512, 'MaxPool', 512, 512, 512, 'MaxPool']
layers = []
in_channel = 3
for cfg in cfgs:
if cfg == "MaxPool": # 池化层
layers += [nn.MaxPool2d(kernel_size=2,stride=2)]
else:
layers += [nn.Conv2d(in_channels=in_channel,out_channels=cfg,kernel_size=3,padding=1)]
layers += [nn.ReLU(True)]
in_channel = cfg
return nn.Sequential(*layers)
net = VGG()
print(net)
