深度学习之图像分类(四)--VGGNet网络结构及感受野计算

深度学习之图像分类(四)VGGNet网络结构及感受野计算

本节学习VGGNet网络结构以及感受野计算,学习视频源于 Bilibili,部分描述参考 知乎专栏,感谢霹雳吧啦Wz,建议大家去看视频学习哦。

请添加图片描述

1. 前言

VGGNet 是 2014 年牛津大学著名研究组 VGG(Visual Geometry Group) 提出,斩获该年 ImageNet 竞赛中 Localization Task 第一名和 Classification Task 第二名 (第一名为 GoogLeNet)。原始论文为 Very deep convolutional networks for large-scale image recognition

该论文在当时最大的亮点是:通过堆叠 3 × 3 3 \times 3 3×3 的卷积核来代替大尺度卷积核,并减少参数量

  • 大卷积核,例如 AlexNet 第一层的 11 × 11 11 \times 11 11×11,参数量大,且难学好
  • 多个 3 × 3 3 \times 3 3×3 的卷积核感受野和一个大的卷积核感受野一致,但是更好学,且参数量更少
    • 两个 3 × 3 3 \times 3 3×3 的卷积核替代一个 5 × 5 5 \times 5 5×5 的卷积核
    • 三个 3 × 3 3 \times 3 3×3 的卷积核替代一个 7 × 7 7 \times 7 7×7 的卷积核
  • 真实人的视网膜初级结构获取的底层特征并非 3 × 3 3 \times 3 3×3 领域,而是更大的例如 11 × 11 11 \times 11 11×11 17 × 17 17 \times 17 17×17 等尺寸

下图左边的表格截取于原论文,作者给出了六个不同的配置,包括比较 LRN(局部响应归一化)、不同卷积核尺寸等。一般而言常用的是 D 配置,即 VGG-16,16 表示 13 个卷积层以及 3 个全连接层。

请添加图片描述

1)A和A-LRN对比:分析LRN在网络中的效果

2)A和B对比:分析在网络靠近输入部分增加卷积层数的效果

3)B和C对比:分析在网络靠近输出部分增加卷积层数的效果

4)C和D对比:分析1X1卷积核和3X3卷积核的对比效果

5)D和E对比:分析在网络靠近输出部分增加卷积层数的效果(这个和3)的作用有点像,只是网络进一步加深)

各个网络的对比结果如下:

请添加图片描述

从这个表中,我们可以对上面5个对比思路下结论:

1)A和A-LRN对比:精度损失0.1%,可以认为精度变化不大,但是LRN操作会增大计算量,所以作者认为在网络中添加LRN意义不大

2)A和B对比:top-1提高0.9%,说明在靠近输入部分增加深度可以提高精度

3)B和C对比:top-1提高0.6%,说明在靠近输出部分增加深度也可以提高精度

4)C和D对比:top-1提高1.1%,说明3X3卷积核的效果要明显由于1X1卷积核的效果

5)D和E对比:top-1下降0.3%,这个我解释不了,不清楚是不是因为网络更深以后,更容易出现过拟合

2. CNN感受野

在卷积神经网络中,决定某一层输出结果中一个元素所对应的输入层的区域大小,被称作感受野(receptive field)。通俗而言,输出 feature map 上的一个单元对应输入层上的区域大小。

请添加图片描述

让我们来看一个例子,下图左边最下面是一个 9 × 9 × 1 9 \times 9 \times 1 9×9×1 的特征矩阵,经过第一个卷积层(卷积核大小为 3 × 3 3 \times 3 3×3 ,步距为 2)。然后再通过一个最大池化下采样操作,(卷积核大小为 2 × 2 2 \times 2 2×2 ,步距为 2),最后得到的特征图大小为 2 × 2 × 1 2 \times 2 \times 1 2×2×1 。从图中可以看出,感受野大小为 5 × 5 5 \times 5 5×5

请添加图片描述

下图给出了感受野大小的计算公式:
F ( i ) = ( F ( i + 1 ) − 1 ) × S t r i d e + K s i z e F(i) = (F(i+1)-1) \times Stride + Ksize F(i)=(F(i+1)1)×Stride+Ksize
其中 F ( i ) F(i) F(i) 为第 i i i 层的感受野,Stride 为第 i i i 层的步距,Ksize 为卷积核或者池化层尺寸。

请添加图片描述

在 VGGNet 论文中作者说:三个 3 × 3 3 \times 3 3×3 的卷积核替代一个 7 × 7 7 \times 7 7×7 的卷积核,卷积核步距为 1。我们进行简单的计算:

Feature map: F = 1
Conv3x3(3) : F = (1 - 1) x 1 + 3 = 3
Conv3x3(2) : F = (3 - 1) x 1 + 3 = 5
Conv3x3(1) : F = (5 - 1) x 1 + 3 = 7

让我们来比较一下使用 7 × 7 7 \times 7 7×7 的卷积核所需要的参数以及使用三个 3 × 3 3 \times 3 3×3 的卷积核所需要的参数,假设输入输出通道都为 C C C

  • 7 × 7 × C × C = 49 C 2 7 \times 7 \times C \times C = 49C^2 7×7×C×C=49C2

  • 3 × ( 3 × 3 × C × C ) = 27 C 2 3 \times (3 \times 3 \times C \times C) = 27C^2 3×(3×3×C×C)=27C2

  • 27 / 49 = 0.551 27 / 49 = 0.551 27/49=0.551

注意,这里没有考虑 bias 参数。可见在感受野相等的情况下, 使用三个 3 × 3 3 \times 3 3×3 的卷积核替代一个 7 × 7 7 \times 7 7×7 的卷积核仅有一半的参数量。

3. VGG网络结构

以 VGG16 为例进行讲解,对应配置为 D。表中卷积 conv 默认的步距 stride = 1,padding = 1;最大池化 maxpool 的 kernel size = 2,步距 stride = 2。左下角图对应的就是 VGG16 的网络结构图。

请添加图片描述

最终网络参数量如图所示:
请添加图片描述

INPUT:     [224x224x3]    memory:  224*224*3=150K    weights: 0
CONV3-64:  [224x224x64]   memory:  224*224*64=3.2M   weights: (3*3*3)*64 = 1,728
CONV3-64:  [224x224x64]   memory:  224*224*64=3.2M   weights: (3*3*64)*64 = 36,864
POOL2:     [112x112x64]   memory:  112*112*64=800K   weights: 0
CONV3-128: [112x112x128]  memory:  112*112*128=1.6M  weights: (3*3*64)*128 = 73,728
CONV3-128: [112x112x128]  memory:  112*112*128=1.6M  weights: (3*3*128)*128 = 147,456
POOL2:     [56x56x128]    memory:  56*56*128=400K    weights: 0
CONV3-256: [56x56x256]    memory:  56*56*256=800K    weights: (3*3*128)*256 = 294,912
CONV3-256: [56x56x256]    memory:  56*56*256=800K    weights: (3*3*256)*256 = 589,824
CONV3-256: [56x56x256]    memory:  56*56*256=800K    weights: (3*3*256)*256 = 589,824
POOL2:     [28x28x256]    memory:  28*28*256=200K    weights: 0
CONV3-512: [28x28x512]    memory:  28*28*512=400K    weights: (3*3*256)*512 = 1,179,648
CONV3-512: [28x28x512]    memory:  28*28*512=400K    weights: (3*3*512)*512 = 2,359,296
CONV3-512: [28x28x512]    memory:  28*28*512=400K    weights: (3*3*512)*512 = 2,359,296
POOL2:     [14x14x512]    memory:  14*14*512=100K    weights: 0
CONV3-512: [14x14x512]    memory:  14*14*512=100K    weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512]    memory:  14*14*512=100K    weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512]    memory:  14*14*512=100K    weights: (3*3*512)*512 = 2,359,296
POOL2:     [7x7x512]      memory:  7*7*512=25K       weights: 0
FC:        [1x1x4096]     memory:  4096          weights: 7*7*512*4096 = 102,760,448
FC:        [1x1x4096]     memory:  4096          weights: 4096*4096 = 16,777,216
FC:        [1x1x1000]     memory:  1000          weights: 4096*1000 = 4,096,000

TOTAL memory: 24M * 4 bytes ~= 93MB / image (only forward! ~*2 for bwd)
TOTAL params: 138M parameters

VGGNet 使用了 Multi-Scale 的方法进行数据增强,将原始图像缩放到不同尺寸 S S S,然后再随机裁切 224 × 224 224 \times 224 224×224 的图片,这样能增加很多数据量,对于防止模型过拟合有很不错的效果。实践中,作者令 S S S 在 [256,512] 这个区间内取值,使用 Multi-Scale 获得多个版本的数据,并将多个版本的数据合在一起进行训练。

请添加图片描述

4. 代码

import torch.nn as nn
import torch
import torch.utils.model_zoo as model_zoo

# 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)
    
	# load ImageNet params
    state_dic = model_zoo.load_url(model_urls[model_name])
    del_key = []
    for key, _ in state_dic.items():
        if "classifier" in key:
            del_key.append(key)
    
    for key in del_key:
        del state_dic[key]
    missing_keys, unexpected_keys = model.load_state_dict(state_dic, strict=False)
    return model
<think>嗯,用户想要了解VGGNet网络结构图。首先,我得回忆一下VGGNet的基本信息。VGGNet是由牛津大学的Visual Geometry Group提出的,主要是在2014年的ILSVRC比赛中取得了不错的成绩。它的主要特点是使用了更深的网络结构,并且全部采用3x3的小卷积核。 接下来,我需要确定用户可能需要的具体内容。用户提到“网络结构图”,所以可能需要各层的详细配置,比如卷积层的数量、滤波器尺寸,以及池化层的位置等。VGGNet有不同的版本,比如VGG16和VGG19,数字代表层数。所以应该先说明常见的VGG16和VGG19的结构差异,以及它们共同的架构特点。 然后,要确保回答结构清晰,按照系统级指令的要求,分步骤解释。可能需要从输入开始,逐步介绍每个块的结构,比如每个块包含几个卷积层,然后是池化层,再进入下一个块。同时,注意参数的变化,比如通道数从64开始,每次池化后翻倍,直到512。 另外,用户可能对为什么使用3x3的卷积核感兴趣,虽然问题中没有直接问,但在介绍结构时可以简要提到,比如减少参数数量,增加网络深度和非线性能力。不过,根据用户的问题,可能不需要深入这部分,但如果有余力可以稍微提及。 需要检查是否需要提到全连接层部分,因为VGGNet后面通常有三个全连接层,最后接softmax分类器。这也是结构图中的重要部分,不能遗漏。 还要注意使用LaTeX格式的数学表达式,比如卷积层的尺寸用$3\times3$,通道数用$64$, $128$等,池化层用$2\times2$的max pooling,步长2。确保这些符合系统指令中的格式要求,行内公式用$...$,独立公式用$$...$$,但结构描述可能更多是文字和列举,数学公式可能较少。 另外,用户可能需要一个结构图的文字描述,因为实际图片无法展示,所以需要用文字详细说明各层的顺序和参数。可能需要用列表或者分段来清晰展示每个块的结构。 最后,总结VGGNet的优势,比如结构简单、扩展性强,以及后续的影响,比如被其他网络作为基础结构。同时,可以提到参数量的巨大,比如VGG16有约1.38亿参数,主要来自全连接层,这也为后面改进网络(如ResNet)做了铺垫。 需要确保回答符合中文要求,结构清晰,分步骤说明,并且正确使用LaTeX格式。可能还需要检查是否有错别字或结构错误,比如各层的顺序是否正确,通道数的变化是否符合实际。</think>VGGNet是牛津大学Visual Geometry Group在2014年提出的经典卷积神经网络,其核心设计思想是通过堆叠小尺寸卷积核($3\times3$)构建深层网络。以下是VGG16(16层)网络结构的文字描述和关键特征分析: --- ### 一、整体结构特点 1. **全$3\times3$卷积核**:每层卷积使用$3\times3$小核,配合$1$像素填充(保持特征图尺寸) 2. **$2\times2$最大池化**:空间下采样仅通过池化层实现(步长$2$) 3. **通道数倍增规则**:每次池化后通道数翻倍(64 → 128 → 256 → 512) 4. **全连接层末端**:最后接3个全连接层(含Dropout) --- ### 二、逐层结构分解 (以VGG16为例,输入尺寸$224\times224\times3$) 1. **Block 1** - 2个卷积层:$64$通道,$3\times3$卷积 - $2\times2$最大池化 → 输出$112\times112\times64$ 2. **Block 2** - 2个卷积层:$128$通道,$3\times3$卷积 - $2\times2$最大池化 → 输出$56\times56\times128$ 3. **Block 3** - 3个卷积层:$256$通道,$3\times3$卷积 - $2\times2$最大池化 → 输出$28\times28\times256$ 4. **Block 4** - 3个卷积层:$512$通道,$3\times3$卷积 - $2\times2$最大池化 → 输出$14\times14\times512$ 5. **Block 5** - 3个卷积层:$512$通道,$3\times3$卷积 - $2\times2$最大池化 → 输出$7\times7\times512$ 6. **全连接层** - FC1: $7\times7\times512 \rightarrow 4096$神经元 - FC2: $4096 \rightarrow 4096$神经元(含Dropout) - FC3: $4096 \rightarrow 1000$神经元(对应ImageNet类别) --- ### 三、关键设计解析 1. **小卷积核优势** $$ \text{两个}3\times3\text{卷积} = 2\times(3^2C^2) = 18C^2 \quad \text{vs} \quad \text{一个}5\times5\text{卷积}=25C^2 $$ 在相同感受野下减少参数量,同时增加非线性激活次数 2. **参数分布特点** - 全连接层占比约90%(如FC1含$7\times7\times512\times4096 \approx 1.03$亿参数) - 这也是后续网络(如ResNet)改进的重点方向 --- ### 、结构图文字描述 (因无法直接显示图片,描述特征图尺寸变化) ``` 输入224x224x3 → 卷积x2 → 池化 → 112x112x64 → 卷积x2 → 池化 → 56x56x128 → 卷积x3 → 池化 → 28x28x256 → 卷积x3 → 池化 → 14x14x512 → 卷积x3 → 池化 → 7x7x512 → 展平 → 全连接x3 → 输出 ``` --- ### 五、延伸说明 - **VGG19**:在Block3-5各增加1个卷积层(总层数19) - **影响**:证明了网络深度的重要性,启发了后续ResNet等网络的设计 - **应用场景**:虽然当前较少直接使用,但其特征提取能力仍被用于迁移学习 如果需要更具体的参数计算或与其他网络的对比分析,可以进一步补充说明。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木卯_THU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值