VGG-传统神经网络之巅峰

本文详细介绍了VGGNet,一种由牛津大学提出的深度卷积神经网络,它在ILSVRC竞赛中的优异表现和3x3卷积核心。VGG16结构、模型特性(如小卷积核、堆叠设计)及如何通过预训练加速训练过程都被深入剖析,并提供了PyTorch实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. VGG简介

VGGNet是由牛津大学视觉几何小组(Visual Geometry Group, VGG)提出的一种深层卷积网络结构,他们以7.32%的错误率赢得了2014年ILSVRC分类任务的亚军(冠军由GoogLeNet以6.65%的错误率夺得)和25.32%的错误率夺得定位任务(Localization)的第一名(GoogLeNet错误率为26.44%),网络名称VGGNet取自该小组名缩写。VGGNet是首批把图像分类的错误率降低到10%以内模型,同时该网络所采用的3×33\times33×3卷积核的思想是后来许多模型的基础,该模型发表在2015年国际学习表征会议(International Conference On Learning Representations, ICLR)后至今被引用的次数已经超过1万4千余次。

2. 模型结构

在这里插入图片描述
在原论文中的VGGNet包含了6个版本的演进,分别对应VGG11、VGG11-LRN、VGG13、VGG16-1、VGG16-3和VGG19,不同的后缀数值表示不同的网络层数(VGG11-LRN表示在第一层中采用了LRN的VGG11,VGG16-1表示后三组卷积块中最后一层卷积采用卷积核尺寸为1×11\times11×1,相应的VGG16-3表示卷积核尺寸为3×33\times33×3),本节介绍的VGG16为VGG16-3。图中的VGG16体现了VGGNet的核心思路,使用3×33\times33×3的卷积组合代替大尺寸的卷积(2个3×3卷积即可与3\times3卷积即可与3×35×55\times55×5卷积拥有相同的感受视野),网络参数设置如表所示。

网络层输入尺寸核尺寸输出尺寸参数个数
卷积层C11C_{11}C11224×224×3224\times224\times3224×224×33×3×64/13\times3\times64/13×3×64/1224×224×64224\times224\times64224×224×64(3×3×3+1)×64(3\times3\times3+1)\times64(3×3×3+1)×64
卷积层C12C_{12}C12224×224×64224\times224\times64224×224×643×3×64/13\times3\times64/13×3×64/1224×224×64224\times224\times64224×224×64(3×3×64+1)×64(3\times3\times64+1)\times64(3×3×64+1)×64
下采样层Smax1S_{max1}Smax1224×224×64224\times224\times64224×224×642×2/22\times2/22×2/2112×112×64112\times112\times64112×112×64000
卷积层C21C_{21}C21112×112×64112\times112\times64112×112×643×3×128/13\times3\times128/13×3×128/1112×112×128112\times112\times128112×112×128(3×3×64+1)×128(3\times3\times64+1)\times128(3×3×64+1)×128
卷积层C22C_{22}C22112×112×128112\times112\times128112×112×1283×3×128/13\times3\times128/13×3×128/1112×112×128112\times112\times128112×112×128(3×3×128+1)×128(3\times3\times128+1)\times128(3×3×128+1)×128
下采样层Smax2S_{max2}Smax2112×112×128112\times112\times128112×112×1282×2/22\times2/22×2/256×56×12856\times56\times12856×56×128000
卷积层C31C_{31}C3156×56×12856\times56\times12856×56×1283×3×256/13\times3\times256/13×3×256/156×56×25656\times56\times25656×56×256(3×3×128+1)×256(3\times3\times128+1)\times256(3×3×128+1)×256
卷积层C32C_{32}C3256×56×25656\times56\times25656×56×2563×3×256/13\times3\times256/13×3×256/156×56×25656\times56\times25656×56×256(3×3×256+1)×256(3\times3\times256+1)\times256(3×3×256+1)×256
卷积层C33C_{33}C3356×56×25656\times56\times25656×56×2563×3×256/13\times3\times256/13×3×256/156×56×25656\times56\times25656×56×256(3×3×256+1)×256(3\times3\times256+1)\times256(3×3×256+1)×256
下采样层Smax3S_{max3}Smax356×56×25656\times56\times25656×56×2562×2/22\times2/22×2/228×28×25628\times28\times25628×28×256000
卷积层C41C_{41}C4128×28×25628\times28\times25628×28×2563×3×512/13\times3\times512/13×3×512/128×28×51228\times28\times51228×28×512(3×3×256+1)×512(3\times3\times256+1)\times512(3×3×256+1)×512
卷积层C42C_{42}C4228×28×51228\times28\times51228×28×5123×3×512/13\times3\times512/13×3×512/128×28×51228\times28\times51228×28×512(3×3×512+1)×512(3\times3\times512+1)\times512(3×3×512+1)×512
卷积层C43C_{43}C4328×28×51228\times28\times51228×28×5123×3×512/13\times3\times512/13×3×512/128×28×51228\times28\times51228×28×512(3×3×512+1)×512(3\times3\times512+1)\times512(3×3×512+1)×512
下采样层Smax4S_{max4}Smax428×28×51228\times28\times51228×28×5122×2/22\times2/22×2/214×14×51214\times14\times51214×14×512000
卷积层C51C_{51}C5114×14×51214\times14\times51214×14×5123×3×512/13\times3\times512/13×3×512/114×14×51214\times14\times51214×14×512(3×3×512+1)×512(3\times3\times512+1)\times512(3×3×512+1)×512
卷积层C52C_{52}C5214×14×51214\times14\times51214×14×5123×3×512/13\times3\times512/13×3×512/114×14×51214\times14\times51214×14×512(3×3×512+1)×512(3\times3\times512+1)\times512(3×3×512+1)×512
卷积层C53C_{53}C5314×14×51214\times14\times51214×14×5123×3×512/13\times3\times512/13×3×512/114×14×51214\times14\times51214×14×512(3×3×512+1)×512(3\times3\times512+1)\times512(3×3×512+1)×512
下采样层Smax5S_{max5}Smax514×14×51214\times14\times51214×14×5122×2/22\times2/22×2/27×7×5127\times7\times5127×7×512000
全连接层FC1FC_{1}FC17×7×5127\times7\times5127×7×512(7×7×512)×4096(7\times7\times512)\times4096(7×7×512)×40961×40961\times40961×4096(7×7×512+1)×4096(7\times7\times512+1)\times4096(7×7×512+1)×4096
全连接层FC2FC_{2}FC21×40961\times40961×40964096×40964096\times40964096×40961×40961\times40961×4096(4096+1)×4096(4096+1)\times4096(4096+1)×4096
全连接层FC3FC_{3}FC31×40961\times40961×40964096×10004096\times10004096×10001×10001\times10001×1000(4096+1)×1000(4096+1)\times1000(4096+1)×1000

在这里插入图片描述

3. 模型特性

  • 整个网络都使用了同样大小的卷积核尺寸3×33\times33×3和最大池化尺寸2×22\times22×2
  • 1×11\times11×1卷积的意义主要在于线性变换,而输入通道数和输出通道数不变,没有发生降维。
  • 两个3×33\times33×3的卷积层串联相当于1个5×55\times55×5的卷积层,感受野大小为5×55\times55×5。同样地,3个3×33\times33×3的卷积层串联的效果则相当于1个7×77\times77×7的卷积层。这样的连接方式使得网络参数量更小,而且多层的激活函数令网络对特征的学习能力更强。
  • VGGNet在训练时有一个小技巧,先训练浅层的的简单网络VGG11,再复用VGG11的权重来初始化VGG13,如此反复训练并初始化VGG19,能够使训练时收敛的速度更快。
  • 在训练过程中使用多尺度的变换对原始数据做数据增强,使得模型不易过拟合。

4. VGG16模型PyTorch代码实现

import torch
import torch.nn as nn
from torchvision.models.utils import load_state_dict_from_url


#--------------------------------------#
#   VGG16的结构
#--------------------------------------#
class VGG(nn.Module):
    def __init__(self, features, num_classes=1000, init_weights=True):
        super(VGG, self).__init__()
        self.features = features
        #--------------------------------------#
        #   平均池化到7x7大小
        #--------------------------------------#
        self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
        #--------------------------------------#
        #   分类部分
        #--------------------------------------#
        self.classifier = nn.Sequential(
            nn.Linear(512 * 7 * 7, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, num_classes),
        )
        if init_weights:
            self._initialize_weights()

    def forward(self, x):
        #--------------------------------------#
        #   特征提取
        #--------------------------------------#
        x = self.features(x)
        #--------------------------------------#
        #   平均池化
        #--------------------------------------#
        x = self.avgpool(x)
        #--------------------------------------#
        #   平铺后
        #--------------------------------------#
        x = torch.flatten(x, 1)
        #--------------------------------------#
        #   分类部分
        #--------------------------------------#
        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')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0, 0.01)
                nn.init.constant_(m.bias, 0)

'''
假设输入图像为(600, 600, 3),随着cfg的循环,特征层变化如下:
600,600,3 -> 600,600,64 -> 600,600,64 -> 300,300,64 -> 300,300,128 -> 300,300,128 -> 150,150,128 -> 150,150,256 -> 150,150,256 -> 150,150,256 
-> 75,75,256 -> 75,75,512 -> 75,75,512 -> 75,75,512 -> 37,37,512 ->  37,37,512 -> 37,37,512 -> 37,37,512
到cfg结束,我们获得了一个37,37,512的特征层
'''

cfg = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M']

#--------------------------------------#
#   特征提取部分
#--------------------------------------#
def make_layers(cfg, batch_norm=False):
    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)
            if batch_norm:
                layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)]
            else:
                layers += [conv2d, nn.ReLU(inplace=True)]
            in_channels = v
    return nn.Sequential(*layers)

def decom_vgg16(pretrained = False):
    model = VGG(make_layers(cfg))
    if pretrained:
        state_dict = load_state_dict_from_url("https://download.pytorch.org/models/vgg16-397923af.pth", model_dir="./model_data")
        model.load_state_dict(state_dict)
    #----------------------------------------------------------------------------#
    #   获取特征提取部分,最终获得一个37,37,1024的特征层
    #----------------------------------------------------------------------------#
    features    = list(model.features)[:30]
    #----------------------------------------------------------------------------#
    #   获取分类部分,需要除去Dropout部分
    #----------------------------------------------------------------------------#
    classifier  = list(model.classifier)
    del classifier[6]
    del classifier[5]
    del classifier[2]

    features    = nn.Sequential(*features)
    classifier  = nn.Sequential(*classifier)
    return features, classifier
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Fighting_1997

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

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

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

打赏作者

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

抵扣说明:

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

余额充值