面试官必问:一文读懂VGG、GoogleNet、ResNet到底是什么?

在正文开始之前,先给大家带来一个超值福利!

为了方便同学们快速开启人工智能学习计划,在学习过程中少走弯路用最快的效率入门Ai并开始实战项目。

我们整理了近200个Ai实战案例和项目,这些并不是网上搜集来的,而是我们这五年线上线下教学所开发和积累的案例。-* 可以说都是反复迭代更新出来的,适合同学们来进行循序渐进的学习与练手。需要的扫码

VGG

简介

VGG(Visual Geometry Group)是由牛津大学视觉几何组提出的深度卷积神经网络,它在 2014 年的 ImageNet 大规模视觉识别挑战赛(ILSVRC)中取得了优异的成绩。VGG 的主要贡献在于证明了增加网络的深度可以显著提高模型的性能,其网络结构简单且规整,具有很强的可扩展性。

VGG 网络结构 

VGG 网络有多个版本,常见的有 VGG11、VGG13、VGG16 和 VGG19,其中数字代表网络中卷积层和全连接层的总数。以 VGG16 为例,其网络结构如下:

  1. 输入层:接收固定大小的图像(如 224x224x3)。

  2. 卷积层:采用多个 3x3 的小卷积核进行卷积操作,通过堆叠多个卷积层来增加网络的深度。每个卷积层后都跟有 ReLU 激活函数。

  3. 池化层:在部分卷积层后使用最大池化(Max Pooling),池化窗口大小为 2x2,步长为 2,用于降低特征图的分辨率。

  4. 全连接层:共有 3 个全连接层,前两个全连接层各有 4096 个神经元,最后一个全连接层有 1000 个神经元,对应 ImageNet 数据集的 1000 个类别。最后一个全连接层的输出通过 softmax 函数转换为概率分布,用于分类。

    这也太全了吧!AlexNet、ResNet、VGG、GoogleNet、模型微调、图像增强方法一次性学会计算机视觉之图像分类入门到实战课程!

代码实现 

import torch
from torch import nn

# VGG16 网络结构
def vgg_block(num_convs, in_channels, out_channels):
    layers = []
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
        layers.append(nn.ReLU())
        in_channels = out_channels
    layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
    return nn.Sequential(*layers)

conv_arch = ((2, 3, 64), (2, 64, 128), (3, 128, 256), (3, 256, 512), (3, 512, 512))

def vgg(conv_arch):
    conv_blks = []
    in_channels = 3
    for (num_convs, in_channels, out_channels) in conv_arch:
        conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
    return nn.Sequential(
        *conv_blks,
        nn.Flatten(),
        nn.Linear(512 * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
        nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
        nn.Linear(4096, 1000)
    )

net = vgg(conv_arch)

VGG 特点

  • 小卷积核:使用多个 3x3 的小卷积核代替大卷积核,在减少参数数量的同时增加了网络的非线性,提高了模型的表达能力。

  • 深度结构:通过堆叠多个卷积层和全连接层,增加了网络的深度,从而能够学习到更复杂的特征。

  • 简单规整:网络结构简单且规整,易于实现和理解。

GoogleNet

简介

GoogleNet(也称为 Inception 网络)是由 Google 团队在 2014 年提出的深度卷积神经网络,它在 ImageNet 挑战赛中夺冠。GoogleNet 的主要创新点在于引入了 Inception 模块,通过在一个模块中并行使用不同大小的卷积核和池化操作,能够同时捕捉不同尺度的特征,提高了模型的性能和计算效率。

GoogleNet 网络结构

GoogleNet 主要由多个 Inception 模块和少量的卷积层、池化层、全连接层组成。其整体结构如下:

  1. 输入层:接收固定大小的图像(如 224x224x3)。

  2. 初始卷积层和池化层:使用 7x7 和 3x3 的卷积核进行卷积操作,然后使用最大池化降低特征图的分辨率。

  3. Inception 模块:多个 Inception 模块堆叠在一起,每个 Inception 模块包含多个并行的分支,分别使用不同大小的卷积核和池化操作,最后将各个分支的输出在通道维度上拼接起来。

  4. 全局平均池化层:在网络的最后部分使用全局平均池化层,将特征图的每个通道的平均值作为该通道的输出,减少了全连接层的参数数量。

  5. 输出层:最后一个全连接层的输出通过 softmax 函数转换为概率分布,用于分类。

Inception 模块 

Inception 模块的结构如下:

  • 1x1 卷积:用于降低输入特征图的通道数,减少计算量。

  • 3x3 卷积:捕捉局部特征。

  • 5x5 卷积:捕捉更大尺度的特征。

  • 3x3 最大池化:提供不同尺度的信息。

代码实现 

import torch
from torch import nn

# Inception 模块
class Inception(nn.Module):
    def __init__(self, in_channels, c1, c2, c3, c4):
        super(Inception, self).__init__()
        # 线路1,单1x1卷积层
        self.p1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)
        # 线路2,1x1卷积层后接3x3卷积层
        self.p2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)
        self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
        # 线路3,1x1卷积层后接5x5卷积层
        self.p3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)
        self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
        # 线路4,3x3最大池化层后接1x1卷积层
        self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
        self.p4_2 = nn.Conv2d(in_channels, c4, kernel_size=1)

    def forward(self, x):
        p1 = nn.functional.relu(self.p1_1(x))
        p2 = nn.functional.relu(self.p2_2(nn.functional.relu(self.p2_1(x))))
        p3 = nn.functional.relu(self.p3_2(nn.functional.relu(self.p3_1(x))))
        p4 = nn.functional.relu(self.p4_2(self.p4_1(x)))
        # 在通道维度上连结输出
        return torch.cat((p1, p2, p3, p4), dim=1)

# GoogleNet 网络结构
b1 = nn.Sequential(
    nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
)

b2 = nn.Sequential(
    nn.Conv2d(64, 64, kernel_size=1),
    nn.ReLU(),
    nn.Conv2d(64, 192, kernel_size=3, padding=1),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
)

b3 = nn.Sequential(
    Inception(192, 64, (96, 128), (16, 32), 32),
    Inception(256, 128, (128, 192), (32, 96), 64),
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
)

b4 = nn.Sequential(
    Inception(480, 192, (96, 208), (16, 48), 64),
    Inception(512, 160, (112, 224), (24, 64), 64),
    Inception(512, 128, (128, 256), (24, 64), 64),
    Inception(512, 112, (144, 288), (32, 64), 64),
    Inception(528, 256, (160, 320), (32, 128), 128),
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
)

b5 = nn.Sequential(
    Inception(832, 256, (160, 320), (32, 128), 128),
    Inception(832, 384, (192, 384), (48, 128), 128),
    nn.AdaptiveAvgPool2d((1, 1)),
    nn.Flatten()
)

net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(1024, 1000))

GoogleNet 特点

  • Inception 模块:通过并行使用不同大小的卷积核和池化操作,能够同时捕捉不同尺度的特征,提高了模型的性能和计算效率。

  • 全局平均池化:使用全局平均池化层代替全连接层,减少了参数数量,降低了过拟合的风险。

  • 深度结构:网络深度较大,能够学习到更复杂的特征。

ResNet

简介

ResNet(Residual Network)是由微软研究院的何恺明等人在 2015 年提出的深度卷积神经网络,它在 ImageNet 挑战赛中取得了优异的成绩。ResNet 的主要创新点在于引入了残差块(Residual Block),通过跳跃连接(Skip Connection)解决了深度神经网络中的梯度消失和梯度爆炸问题,使得网络可以训练更深的模型。

ResNet 网络结构

ResNet 主要由多个残差块和少量的卷积层、池化层、全连接层组成。以 ResNet18 为例,其网络结构如下:

  1. 输入层:接收固定大小的图像(如 224x224x3)。

  2. 初始卷积层和池化层:使用 7x7 的卷积核进行卷积操作,然后使用最大池化降低特征图的分辨率。

  3. 残差块:多个残差块堆叠在一起,每个残差块包含两个 3x3 的卷积层和一个跳跃连接。跳跃连接将输入直接加到卷积层的输出上,使得网络可以学习到残差映射。

  4. 全局平均池化层:在网络的最后部分使用全局平均池化层,将特征图的每个通道的平均值作为该通道的输出,减少了全连接层的参数数量。

  5. 输出层:最后一个全连接层的输出通过 softmax 函数转换为概率分布,用于分类。

残差块

残差块的结构如下:

  • 卷积层:包含两个 3x3 的卷积层,每个卷积层后都跟有 ReLU 激活函数。

  • 跳跃连接:将输入直接加到卷积层的输出上,使得网络可以学习到残差映射。

代码实现

import torch
from torch import nn

# 残差块
class Residual(nn.Module):
    def __init__(self, in_channels, out_channels, use_1x1conv=False, stride=1):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, stride=stride)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        if use_1x1conv:
            self.conv3 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride)
        else:
            self.conv3 = None
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.bn2 = nn.BatchNorm2d(out_channels)

    def forward(self, X):
        Y = nn.functional.relu(self.bn1(self.conv1(X)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            X = self.conv3(X)
        Y += X
        return nn.functional.relu(Y)

# ResNet18 网络结构
b1 = nn.Sequential(
    nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),
    nn.BatchNorm2d(64), nn.ReLU(),
    nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
)

def resnet_block(in_channels, out_channels, num_residuals, first_block=False):
    blk = []
    for i in range(num_residuals):
        if i == 0 and not first_block:
            blk.append(Residual(in_channels, out_channels, use_1x1conv=True, stride=2))
        else:
            blk.append(Residual(out_channels, out_channels))
    return blk

b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))

net = nn.Sequential(
    b1, b2, b3, b4, b5,
    nn.AdaptiveAvgPool2d((1, 1)),
    nn.Flatten(),
    nn.Linear(512, 1000)
)

ResNet 特点

  • 残差块:通过跳跃连接解决了深度神经网络中的梯度消失和梯度爆炸问题,使得网络可以训练更深的模型。

  • 深度结构:网络深度较大,能够学习到更复杂的特征。

  • 高效性:残差块的设计使得网络在增加深度的同时,计算量并没有显著增加。

想要完整可运行代码?我们为大家准备了近200个AI实战代码,打开即可运行!机智的小伙伴已经开始点赞扫码啦!

小结

本期深入探讨了经典 CNN 架构及计算机视觉相关的多个方面:

  • 经典 CNN 架构剖析

    • VGG:以简单规整的结构,通过堆叠小卷积核和全连接层增加深度,证明了深度对模型性能的提升作用。

    • GoogleNet:引入 Inception 模块,并行使用不同卷积核和池化操作,结合全局平均池化,提升了性能与计算效率。

    • ResNet:凭借残差块和跳跃连接,解决了深度网络的梯度问题,使网络可训练更深。


 有以下论文写作问题的可以扫下方名片详聊

前沿顶会、期刊论文、综述文献浩如烟海,不知道学习路径,无从下手?

没时间读、不敢读、不愿读、读得少、读不懂、读不下去、读不透彻一篇完整的论文?

CVPR、ICCV、ECCV、ICLR、NeurlPS、AAAI……想发表顶会论文,找不到创新点?

读完论文,仍旧无法用代码复现……

然而,导师时常无法抽出时间指导,想写论文却无人指点…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值