论文信息
论文名称:Very Deep Convolutional Networks For Large-Scale Image Recognition
论文地址:https://arxiv.org/pdf/1409.1556.pdf
发表期刊: ICLR
发表年份: 2015
论文详情:VGGNet是2014年ILSVRC(ImageNet Large Scale Visual Recognition Challenge大规模视觉识别挑战赛)竞赛的第二名
,解决ImageNet中的1000类图像分类和定位问题,第一名是GoogLeNet
。VGG全称是Visual Geometry Group,因为是由Oxford的Visual Geometry Group提出的。AlexNet问世之后,很多学者通过改进AlexNet的网络结构来提高自己的准确率,主要有两个方向:小卷积核和多尺度
。而VGG的作者们则选择了另外一个方向,即加深网络深度
。主要工作是证明了增加网络的深度能够在一定程度上影响网络最终的性能。
摘要
在这项工作中,我们研究了在大规模图像识别设置中卷积网络深度对其准确性的影响。我们的主要贡献是使用具有非常小(3×3)卷积滤波器的架构对增加深度的网络进行了彻底的评估,这表明通过将深度提高到16–19个权重层,可以实现对现有技术配置的显著改进。这些发现是我们提交的ImageNet Challenge 2014的基础,我们的团队在本地化和分类方面分别获得了第一和第二名。我们还表明,我们的表示可以很好地推广到其他数据集,在那里它们获得了最先进的结果。我们已经公开了我们的两个性能最好的ConvNet模型,以促进在计算机视觉中使用深度视觉表示的进一步研究。
主要工作
作者做了六组实验,对应6个不同的网络模型,这六个网络深度逐渐递增的同时,也有各自的特点。实验表明最后两组,即深度最深的两组16和19层的VGGNet网络模型在分类和定位任务上的效果最好。
各组的区别:
A:起始。
A-LRN:加了LRN,这是AlexNet里提出来的。
B:加了两个卷积层。
C: 进一步叠加了3个卷积层,但是加的是1 * 1的kernel。
D:将C中1 * 1的卷积核替换成了3 * 3的,即VGG16。
E:在D的基础上进一步叠加了3个3*3卷积层,即VGG19。
VGG16包含了16个隐藏层(13个卷积层和3个全连接层),VGG19包含了19个隐藏层(16个卷积层和3个全连接层),如下图所示。
代码实现
(1)pytorch官方实现源码
https://github.com/pytorch/vision/blob/main/torchvision/models/vgg.py
(2)其他实现
import torch.nn as nn
import torch
# official pretrain weights
model_urls = {
'vgg11': 'https://download.pytorch.org/models/vgg11-bbd30ac9.pth',
'vgg13': 'https://download.pytorch.org/models/vgg13-c768596a.pth',
'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth',
'vgg19': 'https://download.pytorch.org/models/vgg19-dcbb9e9d.pth'
}
class VGG(nn.Module):
def __init__(self, features, num_classes=1000, init_weights=False):
super(VGG, self).__init__()
self.features = 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, num_classes)
)
if init_weights:
self._initialize_weights()
def forward(self, x):
# N x 3 x 224 x 224
x = self.features(x)
# N x 512 x 7 x 7
x = torch.flatten(x, start_dim=1)
# N x 512*7*7
x = self.classifier(x)
return x
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
# nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
nn.init.xavier_uniform_(m.weight)
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.xavier_uniform_(m.weight)
# nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
def make_features(cfg: list):
layers = []
in_channels = 3
for v in cfg:
if v == "M":
layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
else:
conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
layers += [conv2d, nn.ReLU(True)]
in_channels = v
return nn.Sequential(*layers)
cfgs = {
'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}
def vgg(model_name="vgg16", **kwargs):
assert model_name in cfgs, "Warning: model number {} not in cfgs dict!".format(model_name)
cfg = cfgs[model_name]
model = VGG(make_features(cfg), **kwargs)
return model
参考文献
http://www.xbhp.cn/news/55760.html
https://blog.csdn.net/qq_43307074/article/details/126027852