VGG

VGG的提出者所在实验室名字为Visual Geometry Group ,因此就地取名,VGG诞生了。

VGG通过堆叠大量的VGG块,实现了更深的网络结构。

这里的VGG块,包含了多个卷积层一个池化层:

  • 卷积层的卷积核尺寸为3*3,stride为1,padding为1;这种结构保证了输入图片(或特征图)经过卷积后得到的特征图的尺寸与输入尺寸是一样的。也就是或,卷积仅仅改变通道数,而不改变图像(特征图)的尺寸。

  • 池化层的池化窗口尺寸和stride都是2,从而使得特征图的尺寸减半。

在堆叠的多个VGG块之后,是一些全连接层,负责最后的分类结果输出。

根据网络层数的不同,VGG有多个版本,如下图:

可以看出,不同版本之间的差异体现在卷积层(VGG 块个数不同),而全连接层是通用的。

在代码实现时,我们将写一个基本通用的框架,它可以帮助我们快捷实现不同版本的VGG。

注意:

  • 我们将忽略现在已经不怎么使用的LRN,并且会添加一些现在常用的网络层,如ReLU,BN等。
  • 对于图中的第4列(C),该框架不是通用的,因为含有1*1卷积。不过这对于实现来说完全不是问题,比如将全部层堆叠在一起,简单粗暴。不过这不是本文的重点。

好了,开始实现吧~

PyTorch 实现VGG

我们可以用一个序列来保存网络的结构,以VGG16为例(上图中第5列,D),其网络结构可表示如下:

1
VGG16=[64,64,'M',128,128,'M',256,256,256,'M',512,512,512,'M',512,512,512,'M']

数字代表卷积层输出通道数,’M’代表池化层。

第一个卷积层的输入通道数需要手动传入,其余参数都是固定的,无需显式写出。

VGG 网络通用框架代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class VGG_net(nn.Module):
def __init__(self,in_channels,architecture,num_classes=1000):
super().__init__()
self.in_channels=in_channels
self.conv_layers=self.create_conv_layers(architecture)
self.fcs=nn.Sequential(
nn.Flatten(start_dim=1),
nn.Linear(512*7*7,4096),#224/(2**5)=7
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096,4096),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096,num_classes)
)

def forward(self,x):
x=self.conv_layers(x)
#x=x.reshape(x.shape[0],-1)
x=self.fcs(x)
return x

def create_conv_layers(self,architecture):
layers=[]
in_channels=self.in_channels
for x in architecture:
if type(x)==int:
out_channels=x
layers+=[nn.Conv2d(in_channels=in_channels,out_channels=out_channels,kernel_size=(3,3),stride=(1,1),padding=(1,1)),
nn.BatchNorm2d(x),
nn.ReLU()]
in_channels=x #下一个卷积层的输入通道数是当前卷积层的输出通道数
elif x=='M':
layers+=[nn.MaxPool2d(kernel_size=(2,2),stride=(2,2))]

return nn.Sequential(*layers)

实例化一个VGG 类,手动将输入图片的通道数(RGB图一般是3)传给in_channels,将VGG16的网络结构序列传给architecture

create_conv_layers方法使用接收到的architecture来构造堆叠的VGG块。

现在,来测试一下构造好的VGG16的效果:

输入一张224*224的3通道图片,最后成功输出该图片所属类别的概率分布(一个1000维的向量)。

如果你想要实现VGG19,只需修改网络结构序列为:

1
VGG19=[64,64,'M',128,128,'M',256,256,256,256,'M',512,512,512,512,'M',512,512,512,512,'M']

然后实例化如下:

1
model_VGG19=VGG_net(in_channels=3,architecture=VGG19,num_classes=1000)

在实际使用时,num_classes可以根据具体问题进行修改,比如2分类问题,那么num_classes就应该设置为2。

以上。