0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

PyTorch教程-8.2. 使用块的网络 (VGG)

jf_pJlTbmA9 来源:PyTorch 作者:PyTorch 2023-06-05 15:44 次阅读

虽然 AlexNet 提供了深度 CNN 可以取得良好结果的经验证据,但它没有提供通用模板来指导后续研究人员设计新网络。在接下来的部分中,我们将介绍几个常用于设计深度网络的启发式概念。

该领域的进展反映了芯片设计中 VLSI(超大规模集成)的进展,工程师从将晶体管放置到逻辑元件再到逻辑块(Mead,1980 年)。同样,神经网络架构的设计也变得越来越抽象,研究人员从单个神经元的角度思考到整个层,现在转向块,重复层的模式。十年后,这已经发展到研究人员使用整个训练模型将它们重新用于不同但相关的任务。此类大型预训练模型通常称为 基础模型 (Bommasani等人,2021 年)。

回到网络设计。使用块的想法首先出现于牛津大学的视觉几何组 (VGG),在他们同名的VGG网络中(Simonyan 和 Zisserman,2014 年)。通过使用循环和子例程,可以使用任何现代深度学习框架轻松地在代码中实现这些重复结构。

import torch
from torch import nn
from d2l import torch as d2l

from mxnet import init, np, npx
from mxnet.gluon import nn
from d2l import mxnet as d2l

npx.set_np()

import jax
from flax import linen as nn
from d2l import jax as d2l

import tensorflow as tf
from d2l import tensorflow as d2l

8.2.1. VGG 块

CNN 的基本构建块是以下序列:(i) 带有填充的卷积层以保持分辨率,(ii) 非线性,例如 ReLU,(iii) 池化层,例如最大池化以减少解决。这种方法的问题之一是空间分辨率下降得非常快。特别是,这强加了一个硬限制log2⁡d网络上所有维度之前的卷积层(d) 用完了。例如,在 ImageNet 的情况下,以这种方式不可能有超过 8 个卷积层。

Simonyan 和 Zisserman ( 2014 )的关键思想是以 块的形式通过最大池化在下采样之间使用多个卷积。他们主要感兴趣的是深度网络还是宽网​​络表现更好。例如,连续应用两个 3×3卷积接触与单个相同的像素 5×5卷积确实如此。同时,后者使用了大约同样多的参数(25⋅c2) 三个 3×3卷积做(3⋅9⋅c2). 在相当详细的分析中,他们表明深度和狭窄的网络明显优于浅层网络。这将深度学习置于对具有超过 100 层的典型应用的更深网络的追求上。堆叠3×3卷积已成为后来的深度网络的黄金标准(最近Liu等人( 2022 )才重新考虑的设计决策)。因此,小卷积的快速实现已成为 GPU 的主要内容 (Lavin 和 Gray,2016 年)。

回到 VGG:一个 VGG 块由一系列卷积组成 3×3填充为 1 的内核(保持高度和宽度)后跟一​​个2×2步长为 2 的最大池化层(每个块后将高度和宽度减半)。在下面的代码中,我们定义了一个函数vgg_block来实现一个 VGG 块。

下面的函数有两个参数,对应于卷积层数num_convs和输出通道数 num_channels。

def vgg_block(num_convs, out_channels):
  layers = []
  for _ in range(num_convs):
    layers.append(nn.LazyConv2d(out_channels, kernel_size=3, padding=1))
    layers.append(nn.ReLU())
  layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
  return nn.Sequential(*layers)

def vgg_block(num_convs, num_channels):
  blk = nn.Sequential()
  for _ in range(num_convs):
    blk.add(nn.Conv2D(num_channels, kernel_size=3,
             padding=1, activation='relu'))
  blk.add(nn.MaxPool2D(pool_size=2, strides=2))
  return blk

def vgg_block(num_convs, out_channels):
  layers = []
  for _ in range(num_convs):
    layers.append(nn.Conv(out_channels, kernel_size=(3, 3), padding=(1, 1)))
    layers.append(nn.relu)
  layers.append(lambda x: nn.max_pool(x, window_shape=(2, 2), strides=(2, 2)))
  return nn.Sequential(layers)

def vgg_block(num_convs, num_channels):
  blk = tf.keras.models.Sequential()
  for _ in range(num_convs):
    blk.add(
      tf.keras.layers.Conv2D(num_channels, kernel_size=3,
                  padding='same', activation='relu'))
  blk.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))
  return blk

8.2.2. VGG网络

与 AlexNet 和 LeNet 一样,VGG 网络可以分为两部分:第一部分主要由卷积层和池化层组成,第二部分由与 AlexNet 相同的全连接层组成。关键区别在于卷积层在保持维数不变的非线性变换中分组,然后是分辨率降低步骤,如图 8.2.1所示。

poYBAGR9NYmAAu3EAATuF75_NS8172.svg

图 8.2.1从 AlexNet 到 VGG。关键区别在于 VGG 由层块组成,而 AlexNet 的层都是单独设计的。

网络的卷积部分连续连接 图 8.2.1中的几个 VGG 块(也在vgg_block函数中定义)。这种卷积分组是一种在过去十年中几乎保持不变的模式,尽管操作的具体选择已经发生了相当大的修改。该变量 conv_arch由一个元组列表(每个块一个)组成,其中每个元组包含两个值:卷积层数和输出通道数,它们正是调用函数所需的参数vgg_block。因此,VGG 定义了一个网络家族,而不仅仅是一个特定的表现形式。要构建一个特定的网络,我们只需迭代arch以组成块。

class VGG(d2l.Classifier):
  def __init__(self, arch, lr=0.1, num_classes=10):
    super().__init__()
    self.save_hyperparameters()
    conv_blks = []
    for (num_convs, out_channels) in arch:
      conv_blks.append(vgg_block(num_convs, out_channels))
    self.net = nn.Sequential(
      *conv_blks, nn.Flatten(),
      nn.LazyLinear(4096), nn.ReLU(), nn.Dropout(0.5),
      nn.LazyLinear(4096), nn.ReLU(), nn.Dropout(0.5),
      nn.LazyLinear(num_classes))
    self.net.apply(d2l.init_cnn)

class VGG(d2l.Classifier):
  def __init__(self, arch, lr=0.1, num_classes=10):
    super().__init__()
    self.save_hyperparameters()
    self.net = nn.Sequential()
    for (num_convs, num_channels) in arch:
      self.net.add(vgg_block(num_convs, num_channels))
    self.net.add(nn.Dense(4096, activation='relu'), nn.Dropout(0.5),
           nn.Dense(4096, activation='relu'), nn.Dropout(0.5),
           nn.Dense(num_classes))
    self.net.initialize(init.Xavier())

class VGG(d2l.Classifier):
  arch: list
  lr: float = 0.1
  num_classes: int = 10
  training: bool = True

  def setup(self):
    conv_blks = []
    for (num_convs, out_channels) in self.arch:
      conv_blks.append(vgg_block(num_convs, out_channels))

    self.net = nn.Sequential([
      *conv_blks,
      lambda x: x.reshape((x.shape[0], -1)), # flatten
      nn.Dense(4096), nn.relu,
      nn.Dropout(0.5, deterministic=not self.training),
      nn.Dense(4096), nn.relu,
      nn.Dropout(0.5, deterministic=not self.training),
      nn.Dense(self.num_classes)])

class VGG(d2l.Classifier):
  def __init__(self, arch, lr=0.1, num_classes=10):
    super().__init__()
    self.save_hyperparameters()
    self.net = tf.keras.models.Sequential()
    for (num_convs, num_channels) in arch:
      self.net.add(vgg_block(num_convs, num_channels))
    self.net.add(
      tf.keras.models.Sequential([
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(4096, activation='relu'),
      tf.keras.layers.Dropout(0.5),
      tf.keras.layers.Dense(4096, activation='relu'),
      tf.keras.layers.Dropout(0.5),
      tf.keras.layers.Dense(num_classes)]))

原始VGG网络有5个卷积块,其中前两个各有一个卷积层,后三个各有两个卷积层。第一个块有 64 个输出通道,随后的每个块将输出通道的数量加倍,直到该数量达到 512。由于该网络使用 8 个卷积层和 3 个全连接层,因此通常称为 VGG-11。

VGG(arch=((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))).layer_summary(
  (1, 1, 224, 224))

Sequential output shape:   torch.Size([1, 64, 112, 112])
Sequential output shape:   torch.Size([1, 128, 56, 56])
Sequential output shape:   torch.Size([1, 256, 28, 28])
Sequential output shape:   torch.Size([1, 512, 14, 14])
Sequential output shape:   torch.Size([1, 512, 7, 7])
Flatten output shape:    torch.Size([1, 25088])
Linear output shape:     torch.Size([1, 4096])
ReLU output shape:  torch.Size([1, 4096])
Dropout output shape:    torch.Size([1, 4096])
Linear output shape:     torch.Size([1, 4096])
ReLU output shape:  torch.Size([1, 4096])
Dropout output shape:    torch.Size([1, 4096])
Linear output shape:     torch.Size([1, 10])

VGG(arch=((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))).layer_summary(
  (1, 1, 224, 224))

Sequential output shape:   (1, 64, 112, 112)
Sequential output shape:   (1, 128, 56, 56)
Sequential output shape:   (1, 256, 28, 28)
Sequential output shape:   (1, 512, 14, 14)
Sequential output shape:   (1, 512, 7, 7)
Dense output shape: (1, 4096)
Dropout output shape:    (1, 4096)
Dense output shape: (1, 4096)
Dropout output shape:    (1, 4096)
Dense output shape: (1, 10)

VGG(arch=((1, 64), (1, 128), (2, 256), (2, 512), (2, 512)),
  training=False).layer_summary((1, 224, 224, 1))

Sequential output shape:   (1, 112, 112, 64)
Sequential output shape:   (1, 56, 56, 128)
Sequential output shape:   (1, 28, 28, 256)
Sequential output shape:   (1, 14, 14, 512)
Sequential output shape:   (1, 7, 7, 512)
function output shape:    (1, 25088)
Dense output shape: (1, 4096)
custom_jvp output shape:   (1, 4096)
Dropout output shape:    (1, 4096)
Dense output shape: (1, 4096)
custom_jvp output shape:   (1, 4096)
Dropout output shape:    (1, 4096)
Dense output shape: (1, 10)

VGG(arch=((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))).layer_summary(
  (1, 224, 224, 1))

Sequential output shape:   (1, 112, 112, 64)
Sequential output shape:   (1, 56, 56, 128)
Sequential output shape:   (1, 28, 28, 256)
Sequential output shape:   (1, 14, 14, 512)
Sequential output shape:   (1, 7, 7, 512)
Sequential output shape:   (1, 10)

如您所见,我们将每个块的高度和宽度减半,最终达到 7 的高度和宽度,然后展平表示以供网络的完全连接部分处理。 Simonyan 和 Zisserman ( 2014 )描述了 VGG 的其他几种变体。事实上,在引入新架构时,提出具有不同速度-精度权衡的网络系列已经成为常态。

8.2.3. 训练

由于 VGG-11 在计算上比 AlexNet 要求更高,我们构建了一个通道数较少的网络。这对于 Fashion-MNIST 的训练来说绰绰有余。模型训练过程与8.1节AlexNet类似。再次观察验证和训练损失之间的密切匹配,表明只有少量过度拟合。

model = VGG(arch=((1, 16), (1, 32), (2, 64), (2, 128), (2, 128)), lr=0.01)
trainer = d2l.Trainer(max_epochs=10, num_gpus=1)
data = d2l.FashionMNIST(batch_size=128, resize=(224, 224))
model.apply_init([next(iter(data.get_dataloader(True)))[0]], d2l.init_cnn)
trainer.fit(model, data)

pYYBAGR9NY2ALRgLAAFz9nbZ9_c991.svg

model = VGG(arch=((1, 16), (1, 32), (2, 64), (2, 128), (2, 128)), lr=0.01)
trainer = d2l.Trainer(max_epochs=10, num_gpus=1)
data = d2l.FashionMNIST(batch_size=128, resize=(224, 224))
trainer.fit(model, data)

poYBAGR9NZCAQzgBAAFoKAqSRnE162.svg

model = VGG(arch=((1, 16), (1, 32), (2, 64), (2, 128), (2, 128)), lr=0.01)
trainer = d2l.Trainer(max_epochs=10, num_gpus=1)
data = d2l.FashionMNIST(batch_size=128, resize=(224, 224))
trainer.fit(model, data)

poYBAGR9NZKAf5RDAAGYR-srCos434.svg

trainer = d2l.Trainer(max_epochs=10)
data = d2l.FashionMNIST(batch_size=128, resize=(224, 224))
with d2l.try_gpu():
  model = VGG(arch=((1, 16), (1, 32), (2, 64), (2, 128), (2, 128)), lr=0.01)
  trainer.fit(model, data)

pYYBAGR9NZSAWCLTAAF1ABY3Nyk178.svg

8.2.4. 概括

有人可能会争辩说 VGG 是第一个真正现代的卷积神经网络。虽然 AlexNet 引入了许多使深度学习大规模有效的组件,但可以说是 VGG 引入了关键属性,例如多个卷积块以及对深度和窄网络的偏好。它也是第一个实际上是整个类似参数化模型系列的网络,为从业者提供了复杂性和速度之间的充分权衡。这也是现代深度学习框架大放异彩的地方。不再需要生成 XML 配置文件来指定网络,而是通过简单的 Python 代码组装所述网络。

最近 ParNet (Goyal等人,2021 年) 证明,可以通过大量并行计算使用更浅的架构来实现有竞争力的性能。这是一个令人兴奋的发展,希望它能影响未来的建筑设计。不过,在本章的剩余部分,我们将追溯过去十年的科学进步之路。

8.2.5. 练习

与 AlexNet 相比,VGG 在计算方面要慢得多,而且需要更多的 GPU 内存。

比较 AlexNet 和 VGG 所需的参数数量。

比较卷积层和全连接层中使用的浮点运算数量。

您如何减少全连接层产生的计算成本?

当显示与网络各层相关的维度时,我们只能看到与 8 个块(加上一些辅助变换)相关的信息,即使网络有 11 层。剩下的 3 层去了哪里?

使用 VGG 论文(Simonyan 和 Zisserman,2014 年)中的表 1构建其他常见模型,例如 VGG-16 或 VGG-19。

对 Fashion-MNIST 中的分辨率进行上采样8 从28×28到224×224尺寸非常浪费。尝试修改网络架构和分辨率转换,例如,将其输入改为 56 或 84 维。你能在不降低网络准确性的情况下这样做吗?考虑 VGG 论文(Simonyan 和 Zisserman,2014 年),了解在下采样之前添加更多非线性的想法。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 网络
    +关注

    关注

    14

    文章

    7525

    浏览量

    88656
  • pytorch
    +关注

    关注

    2

    文章

    803

    浏览量

    13153
收藏 人收藏

    评论

    相关推荐

    VGG介绍卷积神经网络的模型结构

    VGG在加深网络层数同时为了避免参数过多,在所有层都采用3x3的小卷积核,卷积层步长被设置为1。
    发表于 01-05 09:29 8455次阅读
    <b class='flag-5'>VGG</b>介绍卷积神经<b class='flag-5'>网络</b>的模型结构

    基于PyTorch的深度学习入门教程之使用PyTorch构建一个神经网络

    PyTorch的自动梯度计算 Part3:使用PyTorch构建一个神经网络 Part4:训练一个神经网络分类器 Part5:数据并行化 本文是关于Part3的内容。 Part3:使
    的头像 发表于 02-15 09:40 2080次阅读

    【周易AIPU 仿真】在R329上部署VGG_16网络模型

    经过一周多时间的探索,参考了n篇历程,跑通了俩个网络模型,这里记录一下VGG\_16网络模型的部署。全部操作都是在虚拟机的Ubuntu14.04操...
    发表于 01-25 17:29 1次下载
    【周易AIPU 仿真】在R329上部署<b class='flag-5'>VGG</b>_16<b class='flag-5'>网络</b>模型

    如何搭建VGG网络实现Mnist数据集的图像分类

    如何搭建VGG网络,实现Mnist数据集的图像分类? 2 方法 步骤:
    的头像 发表于 02-14 15:00 677次阅读

    如何使用VGG网络进行MNIST图像分类

    VGG网络,可以应用在人脸识别、图像分类等方面。VGG有两种结构,分别为16层和19层。具体结构在其文献做了详细表述
    的头像 发表于 02-17 15:06 892次阅读
    如何使用<b class='flag-5'>VGG</b><b class='flag-5'>网络</b>进行MNIST图像分类

    PyTorch教程8.2之使用网络(VGG)

    电子发烧友网站提供《PyTorch教程8.2之使用网络(VGG).pdf》资料免费下载
    发表于 06-05 10:11 0次下载
    <b class='flag-5'>PyTorch</b>教程8.2之使用<b class='flag-5'>块</b>的<b class='flag-5'>网络</b>(<b class='flag-5'>VGG</b>)

    PyTorch教程8.4之多分支网络(GoogLeNet)

    电子发烧友网站提供《PyTorch教程8.4之多分支网络(GoogLeNet).pdf》资料免费下载
    发表于 06-05 10:03 0次下载
    <b class='flag-5'>PyTorch</b>教程8.4之多分支<b class='flag-5'>网络</b>(GoogLeNet)

    PyTorch教程8.7之密集连接网络(DenseNet)

    电子发烧友网站提供《PyTorch教程8.7之密集连接网络(DenseNet).pdf》资料免费下载
    发表于 06-05 10:01 0次下载
    <b class='flag-5'>PyTorch</b>教程8.7之密集连接<b class='flag-5'>网络</b>(DenseNet)

    PyTorch教程8.8之设计卷积网络架构

    电子发烧友网站提供《PyTorch教程8.8之设计卷积网络架构.pdf》资料免费下载
    发表于 06-05 10:02 0次下载
    <b class='flag-5'>PyTorch</b>教程8.8之设计卷积<b class='flag-5'>网络</b>架构

    PyTorch教程之循环神经网络

    电子发烧友网站提供《PyTorch教程之循环神经网络.pdf》资料免费下载
    发表于 06-05 09:52 0次下载
    <b class='flag-5'>PyTorch</b>教程之循环神经<b class='flag-5'>网络</b>

    PyTorch教程14.11之全卷积网络

    电子发烧友网站提供《PyTorch教程14.11之全卷积网络.pdf》资料免费下载
    发表于 06-05 11:19 0次下载
    <b class='flag-5'>PyTorch</b>教程14.11之全卷积<b class='flag-5'>网络</b>

    使用PyTorch构建神经网络

    PyTorch是一个流行的深度学习框架,它以其简洁的API和强大的灵活性在学术界和工业界得到了广泛应用。在本文中,我们将深入探讨如何使用PyTorch构建神经网络,包括从基础概念到高级特性的全面解析。本文旨在为读者提供一个完整的
    的头像 发表于 07-02 11:31 667次阅读

    如何使用PyTorch建立网络模型

    PyTorch是一个基于Python的开源机器学习库,因其易用性、灵活性和强大的动态图特性,在深度学习领域得到了广泛应用。本文将从PyTorch的基本概念、网络模型构建、优化方法、实际应用等多个方面,深入探讨使用
    的头像 发表于 07-02 14:08 370次阅读

    PyTorch神经网络模型构建过程

    PyTorch,作为一个广泛使用的开源深度学习库,提供了丰富的工具和模块,帮助开发者构建、训练和部署神经网络模型。在神经网络模型中,输出层是尤为关键的部分,它负责将模型的预测结果以合适的形式输出。以下将详细解析
    的头像 发表于 07-10 14:57 462次阅读

    pytorch中有神经网络模型吗

    当然,PyTorch是一个广泛使用的深度学习框架,它提供了许多预训练的神经网络模型。 PyTorch中的神经网络模型 1. 引言 深度学习是一种基于人工神经
    的头像 发表于 07-11 09:59 653次阅读