【图像分类】一文学会VGGNet(pytorch)
目录
1、模型介绍
VGGNet是由牛津大学视觉几何小组(Visual Geometry Group, VGG)提出的一种深层卷积网络结构,他们以7.32%的错误率赢得了2014年ILSVRC分类任务的亚军(冠军由GoogLeNet以6.65%的错误率夺得)和25.32%的错误率夺得定位任务(Localization)的第一名(GoogLeNet错误率为26.44%),网络名称VGGNet取自该小组名缩写。VGGNet是首批把图像分类的错误率降低到10%以内模型,同时该网络所采用的 卷积核的思想是后来许多模型的基础,该模型发表在2015年国际学习表征会议(International Conference On Learning Representations, ICLR)后至今被引用的次数已经超过1万4千余次,yyds!。很多的物体检测模型的主干网络(例如SSD、M2Det)都是采用VGGNet、还有图像风格迁移、图像分割等等,所以VGGNet是我们深度学习必学的模型之一。
2、模型结构
上图是VGG16-3模型,在原论文中的VGGNet包含了6个版本的演进,分别对应VGG11、VGG11-LRN、VGG13、VGG16-1、VGG16-3和VGG19,如下图:
不同的后缀数值表示不同的网络层数(VGG11-LRN表示在第一层中采用了LRN的VGG11,VGG16-1表示后三组卷积块中最后一层卷积采用卷积核尺寸为1×1 ,相应的VGG16-3表示卷积核尺寸为 3×3),本节介绍的VGG16为VGG16-3,参数的详细配置如下表:
网络层 |
输入尺寸 |
核尺寸 |
输出尺寸 |
参数个数 |
卷积层 C_11 |
224×224×3 |
3×3×64/1 |
224×224×64 |
(3×3×3+1)×64 |
卷积层 C_12 |
224×224×64 |
3×3×64/1 |
224×224×64 |
(3×3×64+1)×64 |
池化 Max Pool 1 |
224×224×64 |
2×2/2 |
112×112×64 |
0 |
卷积层 C_21 |
112×112×64 |
3×3×128/1 |
112×112×128 |
(3×3×64+1)×128 |
卷积层 C_22 |
112×112×128 |
3×3×128/1 |
112×112×128 |
(3×3×128+1)×128 |
池化 Max Pool 2 | 112×112×128 |
2×2/2 |
56×56×128 |
0 |
卷积层 C_31 |
56×56×128 |
3×3×256/1 |
56×56×256 |
(3×3×128+1)×256 |
卷积层 C_32 |
56×56×256 |
3×3×256/1 |
56×56×256 |
(3×3×256+1)×256 |
卷积层 C_33 |
56×56×256 |
3×3×256/1 |
56×56×256 |
(3×3×256+1)×256 |
池化 Max Pool 3 | 56×56×256 |
2×2/2 |
28×28×256 |
0 |
卷积层 C_41 |
28×28×256 |
3×3×512/1 |
28×28×512 |
(3×3×256+1)×512 |
卷积层 C_42 |
28×28×512 |
3×3×512/1 |
28×28×512 |
(3×3×512+1)×512 |
卷积层 C_43 |
28×28×512 |
3×3×512/1 |
28×28×512 |
(3×3×512+1)×512 |
池化 Max Pool 4 | 28×28×512 |
2×2/2 |
14×14×512 |
0 |
卷积层 C_51 |
14×14×512 |
3×3×512/1 |
14×14×512 |
(3×3×512+1)×512 |
卷积层 C_52 |
14×14×512 |
3×3×512/1 |
14×14×512 |
(3×3×512+1)×512 |
卷积层 C_53 |
14×14×512 |
3×3×512/1 |
14×14×512 |
(3×3×512+1)×512 |
池化 Max Pool 5 | 14×14×512 |
2×2/2 |
7×7×512 |
0 |
全连接层 FC_1 |
7×7×512 |
(7×7×512)×4096 |
1×4096 |
(7×7×512+1)×4096 |
全连接层 FC_2 |
1×4096 |
4096×4096 |
1×4096 |
(4096+1)×4096 |
全连接层 FC_3 |
1×4096 |
4096×1000 |
1×1000 |
(4096+1)×1000 |
3、模型特性
- 整个网络都使用了同样大小的卷积核尺寸3×3和最大池化尺寸2×2。
- 1×1卷积的意义主要在于线性变换,而输入通道数和输出通道数不变,没有发生降维。
- 两个3×3的卷积层串联相当于1个5×5的卷积层,感受野大小为5×5。同样地,3个3×3的卷积层串联的效果则相当于1个7×7的卷积层。这样的连接方式使得网络参数量更小,而且多层的激活函数令网络对特征的学习能力更强。
注:VGGNet在训练时有一个小技巧,先训练浅层的的简单网络VGG11,再复用VGG11的权重来初始化VGG13,如此反复训练并初始化VGG19,能够使训练时收敛的速度更快。在训练过程中使用多尺度的变换对原始数据做数据增强,使得模型不易过拟合。
4、Pytorch复现
-
"""
-
vgg16
-
"""
-
class VGG16(nn.Module):
-
-
def __init__(self, num_classes):
-
super(VGG16, self).__init__()
-
-
# calculate same padding:
-
# (w - k + 2*p)/s + 1 = o
-
# => p = (s(o-1) - w + k)/2
-
-
self.block_1 = nn.Sequential(
-
nn.Conv2d(in_channels=3,
-
out_channels=64,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
# (1(32-1)- 32 + 3)/2 = 1
-
padding=1),
-
nn.BatchNorm2d(64),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=64,
-
out_channels=64,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(64),
-
nn.ReLU(),
-
nn.MaxPool2d(kernel_size=(2, 2),
-
stride=(2, 2))
-
)
-
-
self.block_2 = nn.Sequential(
-
nn.Conv2d(in_channels=64,
-
out_channels=128,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(128),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=128,
-
out_channels=128,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(128),
-
nn.ReLU(),
-
nn.MaxPool2d(kernel_size=(2, 2),
-
stride=(2, 2))
-
)
-
-
self.block_3 = nn.Sequential(
-
nn.Conv2d(in_channels=128,
-
out_channels=256,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(256),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=256,
-
out_channels=256,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(256),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=256,
-
out_channels=256,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(256),
-
nn.ReLU(),
-
nn.MaxPool2d(kernel_size=(2, 2),
-
stride=(2, 2))
-
)
-
-
self.block_4 = nn.Sequential(
-
nn.Conv2d(in_channels=256,
-
out_channels=512,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(512),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=512,
-
out_channels=512,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(512),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=512,
-
out_channels=512,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(512),
-
nn.ReLU(),
-
nn.MaxPool2d(kernel_size=(2, 2),
-
stride=(2, 2))
-
)
-
-
self.block_5 = nn.Sequential(
-
nn.Conv2d(in_channels=512,
-
out_channels=512,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(512),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=512,
-
out_channels=512,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(512),
-
nn.ReLU(),
-
nn.Conv2d(in_channels=512,
-
out_channels=512,
-
kernel_size=(3, 3),
-
stride=(1, 1),
-
padding=1),
-
nn.BatchNorm2d(512),
-
nn.ReLU(),
-
nn.MaxPool2d(kernel_size=(2, 2),
-
stride=(2, 2))
-
)
-
-
self.classifier = nn.Sequential(
-
nn.Linear(512, 4096),
-
nn.ReLU(True),
-
nn.Dropout(p=0.65),
-
nn.Linear(4096, 4096),
-
nn.ReLU(True),
-
nn.Dropout(p=0.65),
-
nn.Linear(4096, num_classes),
-
)
-
-
for m in self.modules():
-
if isinstance(m, torch.nn.Conv2d) or isinstance(m, torch.nn.Linear):
-
nn.init.kaiming_uniform_(m.weight, mode='fan_in', nonlinearity='leaky_relu')
-
# nn.init.xavier_normal_(m.weight)
-
if m.bias is not None:
-
m.bias.detach().zero_()
-
-
# self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
-
-
def forward(self, x):
-
-
x = self.block_1(x)
-
x = self.block_2(x)
-
x = self.block_3(x)
-
x = self.block_4(x)
-
x = self.block_5(x)
-
# x = self.avgpool(x)
-
x = x.view(x.size(0), -1)
-
logits = self.classifier(x)
-
probas = F.softmax(logits, dim=1)
-
# probas = nn.Softmax(logits)
-
return probas
-
# return logits
文章来源: wanghao.blog.csdn.net,作者:AI浩,版权归原作者所有,如需转载,请联系作者。
原文链接:wanghao.blog.csdn.net/article/details/117698392
- 点赞
- 收藏
- 关注作者
评论(0)