pytorh学习笔记——cifar10(三)创建VGGNet

基础知识储备:

        VGGNet 是由牛津大学的 Visual Geometry Group (VGG) 提出的一种深度卷积神经网络(CNN)架构,首次发表于2014年的论文《Very Deep Convolutional Networks for Large-Scale Image Recognition》。VGGNet 以其简单而有效的结构著称,并在图像分类和对象识别等任务中取得了优异的性能。

核心特点:
        深度网络:VGGNet 的主要特点是它的深度,常见的版本有 VGG-16 和 VGG-19,分别包含 16 层和 19 层带参数的层(卷积层和全连接层)。VGGNet 通过堆叠多层 3×3 的小卷积核,成功构建了更深的网络。

        小卷积核:VGGNet 使用非常小的卷积核(3×3),而不是较大的卷积核(如 5×5 或 7×7)。3×3 的卷积核有两个优点:

        更少的参数:相比大的卷积核,3×3 的卷积核参数更少,可以有效减少模型的参数量。
        更多的非线性:堆叠多个 3×3 卷积层可以增加网络的非线性,从而增强模型的表达能力。
        固定大小的输入:VGGNet 要求输入的图像尺寸固定为 224×224 像素。这与早期的网络(如 AlexNet)相比是一个较大的变化,AlexNet 可以处理可变尺寸的输入图像。

        通道数的逐步增加:VGGNet 中的卷积层通道数(即特征图的数量)逐步增加,从 64 通道开始,然后是 128、256、512,直到最大的 512 个通道。这种设计模式帮助网络逐步提取更复杂的特征。

        最大池化层:每个卷积层之后通常会跟随一个最大池化层(2×2),这有助于减少特征图的尺寸,并引入一定程度的平移不变性。

        全连接层:在卷积层之后,VGGNet 包含了三个全连接层,其中最后一个全连接层连接到 softmax 层用于分类任务。

VGGNet 的架构:
        VGGNet 常见的架构包括 VGG-16 和 VGG-19,它们的区别在于网络的深度。

        VGG-16:包含 16 层带参数的层,具体结构如下:

        13 层卷积层(3×3 卷积核,通道数逐步增加)
        5 个最大池化层(2×2 池化核)
        3 个全连接层(4096 个神经元,4096 个神经元,1000 个神经元用于 ImageNet 数据集的 1000 类分类)
        VGG-19:包含 19 层带参数的层,卷积层更多,结构类似于 VGG-16,但更深。

优缺点:
        优点:
        简单性:VGGNet 的设计非常简单,卷积层只使用 3×3 的卷积核,并且结构高度一致,易于理解和实现。
        深度带来的性能:由于网络的深度较大,VGGNet 在图像分类等任务上的表现非常好,尤其在 ImageNet 数据集上取得了非常低的错误率。
        迁移学习:VGGNet 预训练的模型在很多计算机视觉任务中被广泛用于迁移学习,例如目标检测、图像分割等。
缺点:
        计算成本高:VGGNet 由于深度和大量的卷积核,计算量非常大,尤其是在推理阶段,模型的计算开销较高。
        参数量大:VGG-16 和 VGG-19 包含大量的参数,尤其是全连接层的参数,导致模型占用的内存较多。
        固定输入尺寸:VGGNet 要求输入图像的尺寸固定为 224×224,这在某些应用场景中不够灵活。
应用:
        VGGNet 在计算机视觉领域得到了广泛应用,包括但不限于:

        图像分类:在 ImageNet 等大规模图像分类任务上表现出色。
        目标检测:VGGNet 被用作很多目标检测算法(如 Faster R-CNN

本demo模仿标准VGG,创建一个简化版的VGG网络。

新建vggNet.py:

import warnings

import torch
import torch.nn as nn
import torch.nn.functional as F

# 忽略警告
warnings.filterwarnings('ignore')


class VGGbase(nn.Module):
    def __init__(self, num_classes=10):
        super(VGGbase, self).__init__()
        self.conv1 = nn.Sequential(  # 定义第1个卷积层
            # Sequential 是一个容器,它可以包含一系列的神经网络层(layers),并按顺序执行它们。具体来说,
            # nn.Sequential( 允许您将多个层定义为一个整体,这个整体可以被视为一个单独的层。
            # 当您向神经网络传递数据时,数据会依次通过 Sequential 中定义的每一层。
            # 这种方式简化了网络结构的定义和理解,尤其是在构建较为复杂的网络时。
            nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),  # 输入通道为3,输出通道为64,卷积核大小为3x3,步长为1,填充为1
            nn.BatchNorm2d(64),  # 批量归一化
            # nn.BatchNorm2d 表示对二维输入进行批量归一化,参数 64 通常代表输入特征的通道数。批量归一化的作用是在神经网络训练过程中,对每一批次的数据进行归一化处理,
            # 使得数据的分布更加稳定,有助于加速训练过程、提高模型的泛化能力。
            nn.ReLU()  # 激活函数
        )
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)  # 最大池化,池化核大小为2x2,步长为2
        # 经过第一层卷积后,图像的尺寸为 16x16,通道数为64

        self.conv2_1 = nn.Sequential(  # 定义第2个卷积层的第一次卷积
            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),  # 输入通道为64,输出通道为128,卷积核大小为3x3,步长为1,填充为1
            nn.BatchNorm2d(128),  # 批量归一化
            nn.ReLU()  # 激活函数
        )

        self.conv2_2 = nn.Sequential(  # 定义第2个卷积层的第二次卷积
            nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),  # 输入通道为64,输出通道为128,卷积核大小为3x3,步长为1,填充为1
            nn.BatchNorm2d(128),  # 批量归一化
            nn.ReLU()  # 激活函数
        )
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)  # 最大池化,池化核大小为2x2,步长为2
        # 经过第二层卷积后,图像的尺寸为 8x8,通道数为128

        self.conv3_1 = nn.Sequential(  # 定义第3个卷积层的第一次卷积
            nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),  # 输入通道为64,输出通道为128,卷积核大小为3x3,步长为1,填充为1
            nn.BatchNorm2d(256),  # 批量归一化
            nn.ReLU()  # 激活函数
        )

        self.conv3_2 = nn.Sequential(  # 定义第3个卷积层的第二次卷积
            nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(256),  # 批量归一化
            nn.ReLU()  # 激活函数
        )
        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
        # 经过第三层卷积后,图像的尺寸为 4x4,通道数为256

        self.conv4_1 = nn.Sequential(  # 定义第4个卷积层的第一次卷积
            nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(512),  # 批量归一化
            nn.ReLU()  # 激活函数
        )

        self.conv4_2 = nn.Sequential(  # 定义第4个卷积层的第二次卷积
            nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(512),  # 批量归一化
            nn.ReLU()  # 激活函数
        )
        self.pool4 = nn.MaxPool2d(kernel_size=2, stride=2)  # 最大池化,池化核大小为2x2,步长为2
        # 经过第四层卷积后,图像的尺寸为 2x2,通道数为512

        self.fc = nn.Linear(512 * 4, num_classes)  # 全连接层,输入为512*4,输出为10

    def forward(self, x):   # 定义前向传播过程
        batch_size = x.size(0)  # 获取输入的batch_size
        x = self.conv1(x)  # 第1个卷积层
        x = self.pool1(x)  # 第1个池化层

        x = self.conv2_1(x)  # 第2个卷积层
        x = self.conv2_2(x)  # 第2个卷积层
        x = self.pool2(x)  # 第2个池化层

        x = self.conv3_1(x)  # 第3个卷积层
        x = self.conv3_2(x)  # 第3个卷积层
        x = self.pool3(x)  # 第3个池化层

        x = self.conv4_1(x)  # 第4个卷积层
        x = self.conv4_2(x)  # 第4个卷积层
        x = self.pool4(x)  # 第4个池化层

        x = x.view(batch_size, -1)  # 将图片展开成一行,-1表示自动计算这一维的大小

        x = self.fc(x)   # 全连接层
        output = F.log_softmax(x, dim=1)  # 对输出进行log_softmax处理

        return output


def VGGNet():  # 定义网络结构的应用函数
    return VGGbase()

猜你喜欢

转载自blog.csdn.net/xulibo5828/article/details/143194612