使用Pytorch实现VGG的一般版本
在前面的博文中,我们已经实现了基于Pytorch的VGG11的搭建以及训练;
在本文中,我们将:
1)进一步理解VGG11 13 16和19
2)实现这些不同的架构;
一、VGG网络中的不同架构
ABDE较为常用;我们称之为VGG11 13 16和19
每个架构在某一特定的卷积层后都有最大池化操作;
同时每次卷积操作完成后我们都将对其进行ReLU激活;
其他需要注意的地方是,他们都有相同的全连接层;
二、使用PYTORCH实现VGG网络
导入包:
import torch import torch.nn as nn
VGG的配置:
1 # VGG configurations according to Table 1 in the paper 2 # https://arxiv.org/pdf/1409.1556v6.pdf 3 # configurations A (VGG11), B (VGG13), D (VGG16), and E (VGG19) 4 vgg_cfgs = { 5 'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 6 'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 7 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 8 'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 9 }
- 利用vgg_cfgs字典,A B C D 这些名字都是他们的键;数字代表每个卷基层的输出通道;M代表了最大池化操作;
从上图中也可以看到每个卷积层都有3*3的卷积核;
这意味着我们可以用一种非常通用的方式来定义卷积层;
一些注意事项:
- 这个论文在发表的时候,作者没有提及是否使用了BN方法在他们的网络层中;BN算法是为了解决在非常深的网络中梯度消失的问题;
- 在后面的时候,使用了BN层,即使是官方的Pytorch版本也使用了BN层;
- 因此我们也会使用BN层;
- 另一个需要注意的地方是在前两个fc层之后使用了dropout。虽然在表2中没有提及,但是作者在训练的时候使用了dropout方法;
网络架构类
1 # VGG neural network class 2 class VGG(nn.Module): 3 def __init__(self, in_channels=3, num_classes=1000, 4 config=vgg_cfgs['A']): 5 super(VGG, self).__init__() 6 self.in_channels = in_channels 7 self.num_classes = num_classes 8 self.config = config 9 10 # select convolutional layer configuration for the VGG net 11 self.covolutional_layers = self.make_conv_layers(self.config) 12 13 self.fully_connected = nn.Sequential( 14 nn.Linear(512*7*7, 4096), 15 nn.ReLU(), 16 nn.Dropout(0.5), 17 nn.Linear(4096, 4096), 18 nn.ReLU(), 19 nn.Dropout(0.5), 20 nn.Linear(4096, num_classes) 21 ) 22 23 # function to create the convolutional layers as per the selected config 24 def make_conv_layers(self, config): 25 layers = [] 26 in_channels = self.in_channels 27 for op in config: 28 if op == 'M': 29 layers += [nn.MaxPool2d(kernel_size=2, stride=1)] 30 else: 31 layers += [ 32 nn.Conv2d(in_channels=in_channels, 33 out_channels=op, kernel_size=3, 34 padding=1), 35 nn.BatchNorm2d(op), 36 nn.ReLU() 37 ] 38 in_channels = op 39 return nn.Sequential(*layers) 40 41 # the forward pass 42 def forward(self, x): 43 x = self.convolutional_layers(x) 44 # flatten to prepare for the fully connected layers 45 x = x.view(x.size(0), -1) 46 x = self.fully_connected(x) 47 return x
模型的调用:
1 if __name__ == '__main__': 2 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 3 config_keys = list(vgg_cfgs.keys()) 4 for i, config in enumerate(config_keys): 5 model = VGG(in_channels=3, num_classes=1000, config=vgg_cfgs[config]).to(device) 6 print(f"Config: {config}, {model}") 7 # total parameters in the model 8 total_params = sum(p.numel() for p in model.parameters()) 9 print(f"[INFO]: {total_params:,} total parameters. \n")