介绍

VGG-Network是K. Simonyan和A. Zisserman在论文“Very Deep Convolutional Networks for Large-Scale Image Recognition”中提出的卷积神经网络模型。该架构在 ImageNet 中实现了 92.7% 的 top-5 测试准确率,该网络拥有超过 1400 万张属于 1000 个类别的图像。它是深度学习领域的著名架构之一,将第1层和第2层的大内核大小的过滤器分别替换为11和5,显示了对 AlexNet 架构的改进,多个3×3内核大小的过滤器相继出现。它经过数周的训练,使用的是 NVIDIA Titan Black GPU。
在这里插入图片描述

VGG16 架构

卷积神经网络的输入是固定大小的 224 × 224 RGB 图像。它所做的唯一预处理是从每个像素中减去在训练数据集上计算的平均 RGB 值,然后图像通过一堆卷积(Conv.)层,其中有一个非常小的感受野为 3 × 3 的过滤器,这是捕捉左/右、上/下概念的最小尺寸和中心部分。在其中一种配置中,它还使用 1 × 1 卷积滤波器,可以将其视为输入通道的线性变换,然后是非线性变换,卷积步幅固定为 1 个像素;卷积层输入的空间填充使得卷积后空间分辨率保持不变,即对于 3 × 3 Conv,填充为 1 个像素,然后空间池化由 5 个最大池化层执行,其中 16 个最大池化层跟在一些 Conv 层之后,但不是所有的 Conv 层。这个最大池化是在一个 2 × 2 像素的窗口上执行的,步长为 2。

在这里插入图片描述
该架构包含一堆卷积层,它们在不同的架构中具有不同的深度,然后是三个全连接(FC)层:前两个 FC 各有 4096 个通道,第三个 FC 执行 1000 路分类,因此包含 1000 个通道,每个类一个通道,最后一层是soft-max层。全连接层的配置在所有网络中都是相似的,所有隐藏层都配备了校正 (ReLU) 非线性。此外,这里的一个网络包含局部响应归一化 (LRN),这种归一化不会提高训练数据集的性能,但使用它会导致内存消耗和计算时间增加。

架构总结

• 模型的输入是固定大小的 224×224224×224 RGB 图像

• 预处理是从每个像素中减去训练集 RGB 值的平均值

• 卷积层 17

       - 步幅固定为 1 像素

       – 3×33×3 的填充是 1 个像素

• 空间池化层

       – 按照惯例,这一层不计入网络深度

       – 空间池化是使用最大池化层完成的

       – 窗口大小为 2×22×2

       - 步幅固定为 2

       – 卷积网络使用 5 个最大池化层

• 全连接层:

       • 第一名:4096 (ReLU)。

       ▪第二:4096(ReLU)。

       ▪第三:1000(Softmax)。

架构配置

下图包含了 VGG 网络的卷积神经网络配置

以下层:

 • VGG-11

 • VGG-11 (LRN)

 • VGG-13

 • VGG-16 (Conv1)

 • VGG-16

 • VGG-19

在这里插入图片描述
上面提到了卷积神经网络配置,每列一个。在下文中,网络以它们的名称 (A-E) 来表示。所有配置都遵循传统设计,仅在深度上有所不同:从网络 A 中的 11 个权重层,即 8 Conv。网络 E 中的 3 个 FC 层到 19 个权重层,即 16 个 Conv 和 3 个 FC 层。每个卷积层的宽度很小,通道数很小,从第一层的 64 开始,然后在每个最大池化层之后继续增加 2 倍,直到达到 512。每个配置的参数数量如下所述,虽然深度很大,但网络中的权值的数目并不大于较浅的网络中的权值的数目,而该网络具有较大的卷积层宽度和感受野。

在这里插入图片描述

训练

• 损失函数是多项逻辑回归
• 学习算法是基于动量反向传播的小批量随机梯度下降 (SGD)

·批量为 256

·动量为 0.9

• 正则化

· L2 权重衰减(惩罚乘数为 0.0005)

·前两个全连接层的 Dropout 设置为 0.5

• 学习率

·初始值:0.01

·当验证集准确性停止提高时,它会降低到 10。

• 尽管与 Alexnet 相比,它具有更多的参数和深度,但 CNN 需要更少的 epoch 来收敛损失函数,因为

·小卷积核和大深度的更多正则化。

·某些层的预初始化。

• 训练图像大小

· S 是同位素重新缩放图像的最小边

· 两种设置S的方法

▪Fix S,称为单尺度训练

▪这里 S = 256 和 S = 384

▪Vary S,称为多尺度训练

▪S 来自 [Smin, Smax] 其中 Smin = 256, Smax = 512

– 然后 224×224224×224
图像是从每次 SGD 迭代的重新缩放图像中随机裁剪的。

主要特征

• VGG16 共有 16 层,具有一些权重。

• 仅使用卷积层和池化层。

• 始终使用 3 x 3 内核进行卷积。20

• 2×2 大小的最大池。

• 1.38 亿个参数。

• 在ImageNet 数据上训练。

• 准确度为 92.7%。

• 另一个版本是 VGG 19,共有 19 层权重。

• 这是一个非常好的深度学习架构,可用于对任何特定任务进行基准测试。

• VGG 的预训练网络是开源的,因此可以开箱即用地用于各种类型的应用程序。

使用pytorch实现 VGG 网络

首先让我们为每个版本的 VGG 网络创建过滤器映射,请参阅上面的配置图像以了解过滤器的数量,即为版本创建一个字典,键名为 VGG11、VGG13、VGG16、VGG19,并根据每个版本的过滤器数量分别创建一个列表。这里列表中的“M”称为 Maxpool 操作。创建一个全局变量来提及架构的版本,然后创建一个名为 VGG_net 的类,其输入为 in_channels 和 num_classes,它接受图像输入通道数和输出类数。初始化Sequential层,然后创建一个名为 create_conv_layers 的函数,它将 VGGnet 架构配置作为输入,这是我们在上面为不同版本创建的列表。当它遇到上面列表中的字母“M”时,它会执行 MaxPool2d 操作。完整的实现代码如下:

import torch
import torch.nn as nn
VGG_types = {
"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",],}


VGGType = "VGG16"
class VGGnet(nn.Module):
    def __init__(self, in_channels=3, num_classes=1000):
        super(VGGnet, self).__init__()
        self.in_channels = in_channels
        self.conv_layers = self.create_conv_layers(VGG_types[VGGType])
        self.fcs = nn.Sequential(
        nn.Linear(512 * 7 * 7, 4096),
        nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 4096),
        nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, num_classes),
        )

    def forward(self, x):
        x = self.conv_layers(x)
        x = x.reshape(x.shape[0], -1)
        x = self.fcs(x)
        return x

    def create_conv_layers(self, architecture):
        layers = []
        in_channels = self.in_channels

        for x in architecture:
            if type(x) == int:
                out_channels = x
                layers += [
                nn.Conv2d(
                in_channels=in_channels,
                out_channels=out_channels,
                kernel_size=(3, 3),
                stride=(1, 1),
                padding=(1, 1),
                ),
                nn.BatchNorm2d(x),
                nn.ReLU(),
                ]
                in_channels = x
            elif x == "M":
                layers += [nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))]

        return nn.Sequential(*layers)


if __name__ == "__main__":
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model = VGGnet(in_channels=3, num_classes=500).to(device)
    print(model)
    x = torch.randn(1, 3, 224, 224).to(device)
    print(model(x).shape)

在上面的测试代码中,给出的类数是 500,输出应为

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐