【图像分类】一文学会VGGNet(pytorch)

举报
AI浩 发表于 2021/12/23 00:29:12 2021/12/23
【摘要】 目录 1、模型介绍 2、模型结构 3、模型特性 4、Pytorch复现 1、模型介绍         VGGNet是由牛津大学视觉几何小组(Visual Geometry Group, VGG)提出的一种深层卷积网络结构,他们以7.32%的错误率赢得了2014年ILSVRC分类任务的...

目录

1、模型介绍

2、模型结构

3、模型特性

4、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复现


  
  1. """
  2. vgg16
  3. """
  4. class VGG16(nn.Module):
  5. def __init__(self, num_classes):
  6. super(VGG16, self).__init__()
  7. # calculate same padding:
  8. # (w - k + 2*p)/s + 1 = o
  9. # => p = (s(o-1) - w + k)/2
  10. self.block_1 = nn.Sequential(
  11. nn.Conv2d(in_channels=3,
  12. out_channels=64,
  13. kernel_size=(3, 3),
  14. stride=(1, 1),
  15. # (1(32-1)- 32 + 3)/2 = 1
  16. padding=1),
  17. nn.BatchNorm2d(64),
  18. nn.ReLU(),
  19. nn.Conv2d(in_channels=64,
  20. out_channels=64,
  21. kernel_size=(3, 3),
  22. stride=(1, 1),
  23. padding=1),
  24. nn.BatchNorm2d(64),
  25. nn.ReLU(),
  26. nn.MaxPool2d(kernel_size=(2, 2),
  27. stride=(2, 2))
  28. )
  29. self.block_2 = nn.Sequential(
  30. nn.Conv2d(in_channels=64,
  31. out_channels=128,
  32. kernel_size=(3, 3),
  33. stride=(1, 1),
  34. padding=1),
  35. nn.BatchNorm2d(128),
  36. nn.ReLU(),
  37. nn.Conv2d(in_channels=128,
  38. out_channels=128,
  39. kernel_size=(3, 3),
  40. stride=(1, 1),
  41. padding=1),
  42. nn.BatchNorm2d(128),
  43. nn.ReLU(),
  44. nn.MaxPool2d(kernel_size=(2, 2),
  45. stride=(2, 2))
  46. )
  47. self.block_3 = nn.Sequential(
  48. nn.Conv2d(in_channels=128,
  49. out_channels=256,
  50. kernel_size=(3, 3),
  51. stride=(1, 1),
  52. padding=1),
  53. nn.BatchNorm2d(256),
  54. nn.ReLU(),
  55. nn.Conv2d(in_channels=256,
  56. out_channels=256,
  57. kernel_size=(3, 3),
  58. stride=(1, 1),
  59. padding=1),
  60. nn.BatchNorm2d(256),
  61. nn.ReLU(),
  62. nn.Conv2d(in_channels=256,
  63. out_channels=256,
  64. kernel_size=(3, 3),
  65. stride=(1, 1),
  66. padding=1),
  67. nn.BatchNorm2d(256),
  68. nn.ReLU(),
  69. nn.MaxPool2d(kernel_size=(2, 2),
  70. stride=(2, 2))
  71. )
  72. self.block_4 = nn.Sequential(
  73. nn.Conv2d(in_channels=256,
  74. out_channels=512,
  75. kernel_size=(3, 3),
  76. stride=(1, 1),
  77. padding=1),
  78. nn.BatchNorm2d(512),
  79. nn.ReLU(),
  80. nn.Conv2d(in_channels=512,
  81. out_channels=512,
  82. kernel_size=(3, 3),
  83. stride=(1, 1),
  84. padding=1),
  85. nn.BatchNorm2d(512),
  86. nn.ReLU(),
  87. nn.Conv2d(in_channels=512,
  88. out_channels=512,
  89. kernel_size=(3, 3),
  90. stride=(1, 1),
  91. padding=1),
  92. nn.BatchNorm2d(512),
  93. nn.ReLU(),
  94. nn.MaxPool2d(kernel_size=(2, 2),
  95. stride=(2, 2))
  96. )
  97. self.block_5 = nn.Sequential(
  98. nn.Conv2d(in_channels=512,
  99. out_channels=512,
  100. kernel_size=(3, 3),
  101. stride=(1, 1),
  102. padding=1),
  103. nn.BatchNorm2d(512),
  104. nn.ReLU(),
  105. nn.Conv2d(in_channels=512,
  106. out_channels=512,
  107. kernel_size=(3, 3),
  108. stride=(1, 1),
  109. padding=1),
  110. nn.BatchNorm2d(512),
  111. nn.ReLU(),
  112. nn.Conv2d(in_channels=512,
  113. out_channels=512,
  114. kernel_size=(3, 3),
  115. stride=(1, 1),
  116. padding=1),
  117. nn.BatchNorm2d(512),
  118. nn.ReLU(),
  119. nn.MaxPool2d(kernel_size=(2, 2),
  120. stride=(2, 2))
  121. )
  122. self.classifier = nn.Sequential(
  123. nn.Linear(512, 4096),
  124. nn.ReLU(True),
  125. nn.Dropout(p=0.65),
  126. nn.Linear(4096, 4096),
  127. nn.ReLU(True),
  128. nn.Dropout(p=0.65),
  129. nn.Linear(4096, num_classes),
  130. )
  131. for m in self.modules():
  132. if isinstance(m, torch.nn.Conv2d) or isinstance(m, torch.nn.Linear):
  133. nn.init.kaiming_uniform_(m.weight, mode='fan_in', nonlinearity='leaky_relu')
  134. # nn.init.xavier_normal_(m.weight)
  135. if m.bias is not None:
  136. m.bias.detach().zero_()
  137. # self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
  138. def forward(self, x):
  139. x = self.block_1(x)
  140. x = self.block_2(x)
  141. x = self.block_3(x)
  142. x = self.block_4(x)
  143. x = self.block_5(x)
  144. # x = self.avgpool(x)
  145. x = x.view(x.size(0), -1)
  146. logits = self.classifier(x)
  147. probas = F.softmax(logits, dim=1)
  148. # probas = nn.Softmax(logits)
  149. return probas
  150. # return logits

 

文章来源: wanghao.blog.csdn.net,作者:AI浩,版权归原作者所有,如需转载,请联系作者。

原文链接:wanghao.blog.csdn.net/article/details/117698392

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。