IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> VGGNet -> 正文阅读

[人工智能]VGGNet

1. 前言

本文使用飞桨(PaddlePaddle)复现卷积神经网络VGGNet。
本人全部文章请参见:博客文章导航目录
本文归属于:经典CNN复现系列
前文:AlexNet

2. VGGNet模型结构

VGGNet是当前最流行的CNN模型之一,由Simonyan和Zisserman在2014年提出,其命名来源于论文作者所在的实验室Visual Geometry Group。VGGNet通过使用一些列大小为3x3的小尺寸卷积核的卷积层和池化层构建深度卷积神经网络,并在深度学习图像分类实践中取得了比较好的效果。VGGNet模型结构简单,至今仍具有较强的应用性,同时其网络结构设计方法和思想也仍具有重要参考价值。
VGGNet系列模型中比较流行的有VGG11、VGG13、VGG16、VGG19,VGGNet模型均由5个卷积模块和3个全连接层组成,其严格使用核大小为3x3步长1的卷积层和核大小为2x2步长2的池化层来提取特征,并在网络的最后面使用三层全连接层,将最后一层全连接层的输出作为分类的预测。 在VGGNet中每层卷积均使用ReLU作为激活函数,在全连接层之后添加dropout来抑制过拟合。不同系列的VGGNet模型各卷积模块输入和输出通道数均相同,只有卷积模块中包含的卷积层数不同,其中VGG16模型结构如下图所示。
图一
VGG16包含13个卷积层和3个全连接层,共16层。其5个卷积模块中卷积层数量分别是 [ 2 , 2 , 3 , 3 , 3 ] [2,2,3,3,3] [2,2,3,3,3]。VGG11的5个卷积模块中卷积层数量分别是 [ 1 , 1 , 2 , 2 , 2 ] [1,1,2,2,2] [1,1,2,2,2],VGG13中分别是 [ 2 , 2 , 2 , 2 , 2 ] [2,2,2,2,2] [2,2,2,2,2],VGG19中分别是 [ 2 , 2 , 4 , 4 , 4 ] [2,2,4,4,4] [2,2,4,4,4]
VGGNet模型的成功证明了增加网络的深度,可以更好的学习图像中的特征模式,从而在图像分类等任务中取得更好的效果。

3. VGGNet核心思想

VGGNet使用多个3x3卷积核叠加代替更大的卷积核,从而减少卷积层参数或增大感受野(Receptive Field)。

感受野:卷积神经网络每一层输出的特征图(feature map)上的像素点在输入图片上映射的区域大小。
如果不能理解为什么叫【感受野】这么怪的名字,请查看这个词【视野】。

两层3x3的卷积核进行步长为1的卷积操作之后,输出特征图上每一个点的感受野是5x5,与一层5x5大小的卷积核进行卷积操作之后得到的特征图上一个点的感受野一致。但是两层3x3的卷积参数共3x3x2=18个,而一层5x5的卷积参数共5x5=25个(均在只有一个输出通道情况下)。因此使用更小的卷积核叠加代替大的卷积核,可以减少模型参数。
如果使用两层3x3的卷积核进行步长为2的卷积操作,输出特征图上每一个点的感受野是15x15。具体计算感受野的公式如下:
R F i = ( R F i ? 1 ) × S t r i d e i ? 1 + K _ S i z e i RF_i=(RF_i-1)\times Stride_{i-1}+K\_Size_i RFi?=(RFi??1)×Stridei?1?+K_Sizei?

  • R F i RF_i RFi?:第 i i i层的感受野
  • S t r i d e i Stride_i Stridei?:第 i i i层的卷积核移动步长
  • K _ S i z e i K\_Size_i K_Sizei?:第 i i i层的卷积核大小

4. VGGNet模型复现

使用飞桨(PaddlePaddle)复现VGGNet,首先定义继承自paddle.nn.LayerVGGBlock类,在__init__方法中根据传入参数定义各卷积、池化层,在forward函数中实现VGGBlock前向计算流程。具体代码如下:

# -*- coding: utf-8 -*-
# @Time    : 2021/8/8 21:33
# @Author  : He Ruizhi
# @File    : vggnet.py
# @Software: PyCharm

import paddle

# VGGNet模型卷积层config
# key: VGGNet网络深度
# value: 每个VGGBlock中卷积层数
VGG_CONFIG = {
    11: [1, 1, 2, 2, 2],
    13: [2, 2, 2, 2, 2],
    16: [2, 2, 3, 3, 3],
    19: [2, 2, 4, 4, 4]
}


class VGGBlock(paddle.nn.Layer):
    """
    VGGNet模型由多个VGGBlock + 多层全连接层组成,每个VGGBlock只有卷积层层数不同,其余均相同
    一个VGGBlock中卷积层输出通道数均相同

    input_channels: VGGBlock输入通道数
    output_channels: VGGBlock各卷积层之间的输入及输出通道数
    groups: VGGBlock包含的卷积层数
    """
    def __init__(self, input_channels, output_channels, groups):
        super(VGGBlock, self).__init__()
        self.groups = groups
        # 类似ReLU、MaxPool2D等无训练参数,且完全相同的模块可以只初始化一次,然后多次复用
        # 甚至可以不用初始化,直接在forward前向计算函数中通过paddle.nn.functional.*调用相关函数
        # 但是如果不在__init__函数中多次显式地定义出来,则在paddle.summary中无法清晰地看到模型结构
        # 为了清晰地在paddle.summary中清晰地看到模型结构,这里会多次显式第初始化ReLU、MaxPool2D等模块
        self.conv1 = paddle.nn.Conv2D(in_channels=input_channels, out_channels=output_channels,
                                      kernel_size=3, stride=1, padding=1, bias_attr=False)
        self.relu1 = paddle.nn.ReLU()
        if groups in [2, 3, 4]:
            self.conv2 = paddle.nn.Conv2D(in_channels=output_channels, out_channels=output_channels,
                                          kernel_size=3, stride=1, padding=1, bias_attr=False)
            self.relu2 = paddle.nn.ReLU()
        if groups in [3, 4]:
            self.conv3 = paddle.nn.Conv2D(in_channels=output_channels, out_channels=output_channels,
                                          kernel_size=3, stride=1, padding=1, bias_attr=False)
            self.relu3 = paddle.nn.ReLU()
        if groups == 4:
            self.conv4 = paddle.nn.Conv2D(in_channels=output_channels, out_channels=output_channels,
                                          kernel_size=3, stride=1, padding=1, bias_attr=False)
            self.relu4 = paddle.nn.ReLU()

        self.max_pool = paddle.nn.MaxPool2D(kernel_size=2, stride=2, padding=0)

    def forward(self, x):
        x = self.relu1(self.conv1(x))
        if self.groups in [2, 3, 4]:
            x = self.relu2(self.conv2(x))
        if self.groups in [3, 4]:
            x = self.relu3(self.conv3(x))
        if self.groups == 4:
            x = self.relu4(self.conv4(x))
        x = self.max_pool(x)
        return x

设置input_channels=4output_channels=64groups=4,实例化VGGBlock对象,并使用paddle.summary查看VGGBlock结构:

    vgg_block = VGGBlock(3, 64, 4)
    paddle.summary(vgg_block, input_size=(None, 3, 224, 224))

打印VGGBlock结构信息如下:

---------------------------------------------------------------------------
 Layer (type)       Input Shape          Output Shape         Param #    
===========================================================================
   Conv2D-1      [[1, 3, 224, 224]]   [1, 64, 224, 224]        1,728     
    ReLU-1      [[1, 64, 224, 224]]   [1, 64, 224, 224]          0       
   Conv2D-2     [[1, 64, 224, 224]]   [1, 64, 224, 224]       36,864     
    ReLU-2      [[1, 64, 224, 224]]   [1, 64, 224, 224]          0       
   Conv2D-3     [[1, 64, 224, 224]]   [1, 64, 224, 224]       36,864     
    ReLU-3      [[1, 64, 224, 224]]   [1, 64, 224, 224]          0       
   Conv2D-4     [[1, 64, 224, 224]]   [1, 64, 224, 224]       36,864     
    ReLU-4      [[1, 64, 224, 224]]   [1, 64, 224, 224]          0       
  MaxPool2D-1   [[1, 64, 224, 224]]   [1, 64, 112, 112]          0       
===========================================================================
Total params: 112,320
Trainable params: 112,320
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 202.12
Params size (MB): 0.43
Estimated Total Size (MB): 203.13
---------------------------------------------------------------------------

定义继承自paddle.nn.LayerVGGNet类,在__init__方法中定义卷积模块和全连接层模块,在forward函数中实现网络前向计算流程。具体代码如下:

class VGGNet(paddle.nn.Layer):
    """
    VGGNet

    config: VGGNet config,定义VGGNet种类
    num_classes: 输出分类数
    """
    def __init__(self, config, num_classes=1000):
        super(VGGNet, self).__init__()

        self.conv_block = paddle.nn.Sequential(
            VGGBlock(3, 64, config[0]),
            VGGBlock(64, 128, config[1]),
            VGGBlock(128, 256, config[2]),
            VGGBlock(256, 512, config[3]),
            VGGBlock(512, 512, config[4])
        )

        self.flatten = paddle.nn.Flatten()

        self.fc_block = paddle.nn.Sequential(
            paddle.nn.Linear(7*7*512, 4096),
            paddle.nn.ReLU(),
            paddle.nn.Dropout(0.5),

            paddle.nn.Linear(4096, 4096),
            paddle.nn.ReLU(),
            paddle.nn.Dropout(0.5),

            paddle.nn.Linear(4096, num_classes)
        )

    def forward(self, x):
        x = self.conv_block(x)
        x = self.flatten(x)
        x = self.fc_block(x)
        return x

设置config=VGG_CONFIG[16],创建VGG16模型对象,并使用paddle.summary查看VGG16结构信息:

if __name__ == '__main__':
    # vgg_block = VGGBlock(3, 64, 4)
    # paddle.summary(vgg_block, input_size=(None, 3, 224, 224))

    vgg16 = VGGNet(VGG_CONFIG[16])
    paddle.summary(vgg16, input_size=(None, 3, 224, 224))

打印VGG16模型结构信息如下:

---------------------------------------------------------------------------
 Layer (type)       Input Shape          Output Shape         Param #    
===========================================================================
   Conv2D-1      [[1, 3, 224, 224]]   [1, 64, 224, 224]        1,728     
    ReLU-1      [[1, 64, 224, 224]]   [1, 64, 224, 224]          0       
   Conv2D-2     [[1, 64, 224, 224]]   [1, 64, 224, 224]       36,864     
    ReLU-2      [[1, 64, 224, 224]]   [1, 64, 224, 224]          0       
  MaxPool2D-1   [[1, 64, 224, 224]]   [1, 64, 112, 112]          0       
  VGGBlock-1     [[1, 3, 224, 224]]   [1, 64, 112, 112]          0       
   Conv2D-3     [[1, 64, 112, 112]]   [1, 128, 112, 112]      73,728     
    ReLU-3      [[1, 128, 112, 112]]  [1, 128, 112, 112]         0       
   Conv2D-4     [[1, 128, 112, 112]]  [1, 128, 112, 112]      147,456    
    ReLU-4      [[1, 128, 112, 112]]  [1, 128, 112, 112]         0       
  MaxPool2D-2   [[1, 128, 112, 112]]   [1, 128, 56, 56]          0       
  VGGBlock-2    [[1, 64, 112, 112]]    [1, 128, 56, 56]          0       
   Conv2D-5      [[1, 128, 56, 56]]    [1, 256, 56, 56]       294,912    
    ReLU-5       [[1, 256, 56, 56]]    [1, 256, 56, 56]          0       
   Conv2D-6      [[1, 256, 56, 56]]    [1, 256, 56, 56]       589,824    
    ReLU-6       [[1, 256, 56, 56]]    [1, 256, 56, 56]          0       
   Conv2D-7      [[1, 256, 56, 56]]    [1, 256, 56, 56]       589,824    
    ReLU-7       [[1, 256, 56, 56]]    [1, 256, 56, 56]          0       
  MaxPool2D-3    [[1, 256, 56, 56]]    [1, 256, 28, 28]          0       
  VGGBlock-3     [[1, 128, 56, 56]]    [1, 256, 28, 28]          0       
   Conv2D-8      [[1, 256, 28, 28]]    [1, 512, 28, 28]      1,179,648   
    ReLU-8       [[1, 512, 28, 28]]    [1, 512, 28, 28]          0       
   Conv2D-9      [[1, 512, 28, 28]]    [1, 512, 28, 28]      2,359,296   
    ReLU-9       [[1, 512, 28, 28]]    [1, 512, 28, 28]          0       
   Conv2D-10     [[1, 512, 28, 28]]    [1, 512, 28, 28]      2,359,296   
    ReLU-10      [[1, 512, 28, 28]]    [1, 512, 28, 28]          0       
  MaxPool2D-4    [[1, 512, 28, 28]]    [1, 512, 14, 14]          0       
  VGGBlock-4     [[1, 256, 28, 28]]    [1, 512, 14, 14]          0       
   Conv2D-11     [[1, 512, 14, 14]]    [1, 512, 14, 14]      2,359,296   
    ReLU-11      [[1, 512, 14, 14]]    [1, 512, 14, 14]          0       
   Conv2D-12     [[1, 512, 14, 14]]    [1, 512, 14, 14]      2,359,296   
    ReLU-12      [[1, 512, 14, 14]]    [1, 512, 14, 14]          0       
   Conv2D-13     [[1, 512, 14, 14]]    [1, 512, 14, 14]      2,359,296   
    ReLU-13      [[1, 512, 14, 14]]    [1, 512, 14, 14]          0       
  MaxPool2D-5    [[1, 512, 14, 14]]     [1, 512, 7, 7]           0       
  VGGBlock-5     [[1, 512, 14, 14]]     [1, 512, 7, 7]           0       
   Flatten-1      [[1, 512, 7, 7]]        [1, 25088]             0       
   Linear-1         [[1, 25088]]          [1, 4096]         102,764,544  
    ReLU-14         [[1, 4096]]           [1, 4096]              0       
   Dropout-1        [[1, 4096]]           [1, 4096]              0       
   Linear-2         [[1, 4096]]           [1, 4096]         16,781,312   
    ReLU-15         [[1, 4096]]           [1, 4096]              0       
   Dropout-2        [[1, 4096]]           [1, 4096]              0       
   Linear-3         [[1, 4096]]           [1, 1000]          4,097,000   
===========================================================================
Total params: 138,353,320
Trainable params: 138,353,320
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 230.46
Params size (MB): 527.78
Estimated Total Size (MB): 758.81
---------------------------------------------------------------------------

5. 参考资料链接

  1. https://aistudio.baidu.com/aistudio/projectdetail/2169490
  2. https://www.icourse163.org/learn/ZJU-1206573810?tid=1206902211#/learn/content?type=detail&id=1235252086&cid=1254983007
  3. https://github.com/PaddlePaddle/PaddleClas/blob/release/2.2/ppcls/arch/backbone/legendary_models/vgg.py
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-08-12 16:36:04  更:2021-08-12 16:37:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 20:29:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码