VGG网络详解

网络背景

VGG网络是由牛津大学 Visual Geometry Group(视觉几何组)的研究团队在2014年提出的经典卷积神经网络架构,其全称为 VGGNet。它在当时(2014年)的 ImageNet Large Scale Visual Recognition Challenge (ILSVRC) 竞赛中取得了优异的成绩,并因其简洁、统一的架构设计成为深度学习计算机视觉领域的重要里程碑。

网络创新

1.统一使用小卷积核代替大尺度卷积核

所有卷积层均采用 3×3小卷积核(stride=1, padding=1),替代AlexNet中的大卷积核(11×11、5×5)。两个3×3卷积堆叠的感受野相当于一个5×5卷积,但参数量更少;三个3×3卷积堆叠的感受野相当于一个7×7卷积,参数量也更小。

2.对深度网络进行探索

VGG团队设计了从 VGG11(11层)到 VGG19(19层)的多个变体,严格保持其他超参数一致,首次系统化研究深度对性能的影响。更深的网络能学习更复杂的特征层次(从边缘→纹理→物体部件→整体对象),但超过19层后,梯度消失问题凸显。

3.严格的架构规范化

所有卷积层使用相同配置(3×3卷积+ReLU),池化层仅用 2×2 MaxPool(stride=2),结构高度统一。可复现性强,迁移学习友好。

网络结构

以VGG16为例:

输入层 (224×224×3 RGB图像)

卷积层1 (64个3×3卷积核) → ReLU → 最大池化 (2×2)

卷积层2 (128个3×3卷积核) → ReLU → 最大池化 (2×2)

卷积层3 (256个3×3卷积核) → ReLU

卷积层4 (256个3×3卷积核) → ReLU

卷积层5 (256个3×3卷积核) → ReLU → 最大池化 (2×2)

卷积层6 (512个3×3卷积核) → ReLU

卷积层7 (512个3×3卷积核) → ReLU

卷积层8 (512个3×3卷积核) → ReLU → 最大池化 (2×2)

卷积层9 (512个3×3卷积核) → ReLU

卷积层10 (512个3×3卷积核) → ReLU

卷积层11 (512个3×3卷积核) → ReLU → 最大池化 (2×2)

展平 (Flatten)

全连接层12 (4096神经元) → ReLU → Dropout (0.5)

全连接层13 (4096神经元) → ReLU → Dropout (0.5)

全连接层14 (1000神经元) → Softmax

输出层 (1000类概率)

网络代码

import torch.nn as nn
import torch


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)
    return model

网络局限性

1. 参数量过大,计算成本高

VGG-16的全连接层(FC-4096 → FC-4096 → FC-1000)占用了约 1.2亿参数(占总参数量的80%以上),导致模型体积庞大(如VGG-16的预训练模型超过500MB)。

2.存在梯度消失/爆炸问题

网络深度达16~19层,但未使用残差连接(ResNet)或批量归一化(BatchNorm),导致梯度反向传播时容易衰减或发散,训练不稳定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值