• 分类神经网络1:VGGNet模型复现


    目录

    分类网络的常见形式

    VGG网络架构

    VGG网络部分实现代码


    分类网络的常见形式

    常见的分类网络通常由特征提取部分分类部分组成。

    特征提取部分实质就是各种神经网络,如VGG、ResNet、DenseNet、MobileNet等。其负责捕获数据的有用信息,一般是通过堆叠多个卷积层和池化层来实现的,这些层有助于检测图像中的边缘、纹理和特征。

    分类部分通常是一个全连接层,负责将特征提取部分输出的信息映射到最终的类别或标签。这些全连接层通常包括一个或多个隐藏层,以及一个输出层,其中输出层的节点数量等于任务中的类别数量。

    VGG网络架构

    论文原址:https://arxiv.org/pdf/1409.1556v6.pdf

    VGG 网络是由牛津大学的Visual Geometry Group 开发的,其结构特点在于使用了多个 3x3 的小卷积核,并通过这些小卷积层的重复堆叠来构建网络,从而能够捕捉到更加复杂和抽象的特征表示。VGG 网络的模型结构如下:

    VGG网络的核心架构可以分为以下几个部分:

    1. 输入层:VGG网络接受224x224像素的RGB图像作为输入。
    2. 卷积层:网络的前几层由多个卷积层组成,每个卷积层都使用3x3的卷积核来提取图像的特征。这些卷积层后面通常跟着一个2x2 最大池化,用于逐步减小特征图的空间尺寸,同时增加特征深度。
    3. 池化层:在卷积层之后,网络使用最大池化层来降低特征图的空间分辨率,这有助于减少计算量并提取更加抽象的特征。
    4. 全连接层:经过多个卷积和池化层之后,网络的特征图被展平并通过几个全连接层进行处理。全连接层的作用是将学习到的特征映射到最终的分类结果。
    5. 输出层:VGG网络的最后是一个softmax层,它将网络的输出转换为概率分布,以便进行多类别的分类任务。

    VGG网络的一个显著特点是其深度,其相关配置信息如下:

    VGG系列不同变体内容如下:

    • VGG A:这是一个基础的配置,没有特别独特的设计。
    • VGG A-LRN:在这个版本中,加入了局部响应归一化(LRN),这是一种在AlexNet中首次使用的技术。不过,LRN在当前的深度学习实践中已经较少被采用。
    • VGG B:相较于A版本,B版本增加了两个卷积层,以增强网络的学习能力。
    • VGG C:在B的基础上,C版本进一步增加了三个卷积层,但这些层使用的是1x1的卷积核。1x1卷积核可以看作是对输入特征图进行线性变换,有助于减少参数数量并增加非线性。
    • VGG D:D版本在C版本的基础上做了调整,将1x1的卷积核替换为3x3的卷积核,这个配置后来被称为VGG16,因为它总共有16层。
    • VGG E:在D版本的基础上,E版本进一步增加了三个3x3的卷积层,形成了VGG19,总共有19层。

    从图中可以看出,随着网络深度的加深,模型变得更为复杂。通常来说,增加网络的深度可以增加模型的表示能力,使其能够学习到更复杂的特征和模式,从而在某些任务上取得更好的性能。然而,随着网络深度的增加,模型的参数数量也会增加,导致模型的复杂度增加,训练和推理的计算成本也会增加,同时可能会增加过拟合的风险。

    VGG网络部分实现代码

    废话不多说,直接上干货

    1. import torch
    2. import torch.nn as nn
    3. __all__ = ["VGG", "vgg11_bn", "vgg13_bn", "vgg16_bn", "vgg19_bn"]
    4. cfg = {
    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. 'C': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
    8. 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
    9. }
    10. class ConvBNReLU(nn.Module):
    11. def __init__(self, in_channels, out_channels, stride=1, kernel_size=3, padding=1):
    12. super(ConvBNReLU, self).__init__()
    13. self.conv = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, stride=stride, padding=padding)
    14. self.bn = nn.BatchNorm2d(num_features=out_channels)
    15. self.relu = nn.ReLU(inplace=True)
    16. def forward(self, x):
    17. x = self.conv(x)
    18. x = self.bn(x)
    19. x = self.relu(x)
    20. return x
    21. class VGG(nn.Module):
    22. def __init__(self, features, num_classes=1000, init_weights=True):
    23. super(VGG, self).__init__()
    24. self.features = features
    25. self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
    26. self.classifier = nn.Sequential(
    27. nn.Linear(512 * 7 * 7, 4096),
    28. nn.ReLU(True),
    29. nn.Dropout(),
    30. nn.Linear(4096, 4096),
    31. nn.ReLU(True),
    32. nn.Dropout(),
    33. nn.Linear(4096, num_classes),
    34. )
    35. if init_weights:
    36. self._initialize_weights()
    37. def forward(self, x):
    38. for layer in self.features:
    39. x = layer(x)
    40. x = self.avgpool(x)
    41. x = torch.flatten(x, 1)
    42. x = self.classifier(x)
    43. return x
    44. def _initialize_weights(self):
    45. for m in self.modules():
    46. if isinstance(m, nn.Conv2d):
    47. nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
    48. if m.bias is not None:
    49. nn.init.constant_(m.bias, 0)
    50. elif isinstance(m, nn.BatchNorm2d):
    51. nn.init.constant_(m.weight, 1)
    52. nn.init.constant_(m.bias, 0)
    53. elif isinstance(m, nn.Linear):
    54. nn.init.normal_(m.weight, 0, 0.01)
    55. nn.init.constant_(m.bias, 0)
    56. def make_layers(cfg):
    57. layers = nn.ModuleList()
    58. in_channels = 3
    59. for i in cfg:
    60. if i == 'M':
    61. layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
    62. else:
    63. layers.append(ConvBNReLU(in_channels=in_channels, out_channels=i))
    64. in_channels = i
    65. return layers
    66. def vgg11_bn(num_classes):
    67. model = VGG(make_layers(cfg['A']), num_classes=num_classes)
    68. return model
    69. def vgg13_bn(num_classes):
    70. model = VGG(make_layers(cfg['B']), num_classes=num_classes)
    71. return model
    72. def vgg16_bn(num_classes):
    73. model = VGG(make_layers(cfg['C']), num_classes=num_classes)
    74. return model
    75. def vgg19_bn(num_classes):
    76. model = VGG(make_layers(cfg['D']), num_classes=num_classes)
    77. return model
    78. if __name__=='__main__':
    79. import torchsummary
    80. device = 'cuda' if torch.cuda.is_available() else 'cpu'
    81. input = torch.ones(2, 3, 224, 224).to(device)
    82. net = vgg16_bn(num_classes=4)
    83. net = net.to(device)
    84. out = net(input)
    85. print(out)
    86. print(out.shape)
    87. torchsummary.summary(net, input_size=(3, 224, 224))
    88. # Total params: 134,285,380

    这只是一个网络架构部分实现代码,其中 cfg 列表是 VGG 卷积和池化后的通道数,大家可以结合 VGG 的配置信息图一起对比理解。希望对大家有所帮助呀!

  • 相关阅读:
    网络安全(黑客)自学
    java毕业设计员工工资管理系统Mybatis+系统+数据库+调试部署
    【码银送书第九期】《ChatGPT 驱动软件开发:AI 在软件研发全流程中的革新与实践》
    记一次 .NET 某RFID标签管理系统 CPU 暴涨分析
    如何安全地访问互联网
    【Redis面试】基础题总结(上)
    【Python】用Python生成图像特效
    【ShardingSphere】单实例模式创建分片表、广播表、单表
    Jmeter扩展---自定义取样器
    3 种方法限制 K8s Pod 磁盘容量使用
  • 原文地址:https://blog.csdn.net/m0_73228309/article/details/138042020