经典神经网络——VGGNet模型论文详解及代码复现

news2024/11/18 20:23:47

论文地址:1409.1556.pdf。 (arxiv.org);1409.1556.pdf (arxiv.org)

项目地址:Kaggle Code

 一、背景

ImageNet Large Scale Visual Recognition Challenge 是李飞飞等人于2010年创办的图像识别挑战赛,自2010起连续举办8年,极大地推动计算机视觉发展。比赛项目涵盖:图像分类(Classification)、目标定位(Object localization)、目标检测(Object detection)、视频目标检测(Object detection from video)、场景分类(Scene classification)、场景解析(Scene parsing)。

VGG Net由牛津大学的视觉几何组(Visual Geometry Group)参加2014年ILSVRC提出的网络模型,它主要的贡献是展示了卷积神经网络的深度(depth)是算法优良性能的关键部分。

VGGNet的产生主要源于2012年AlexNet将深度学习的方法应用到ImageNet的图像分类比赛中并取得了惊人的效果后,大家都竞相效仿并在此基础上做了大量尝试和改进,例如,在卷积层使用更小的卷积核以及更小的步长(Zeiler&Fergus,2013; Sermanet,2014),又或者在整个图像和多个尺度上密集地训练和测试网(Sermanet,2014:Howard,2014)。但这些优化中作者觉得都没有谈到网络深度的工作,因此受到启发,不仅将上面的两种方法应用到自己的网络设计和训练测试阶段,同时想再试试深度对结果的影响。

VGGNet探索了卷积神经网络的深度与其性能之间的关系,成功地构筑了16~19层深的卷积神经网络,证明了增加网络的深度能够在一定程度上影响网络最终的性能,使错误率大幅下降,同时拓展性又很强,迁移到其它图片数据上的泛化性也非常好。到目前为止,VGG仍然被用来提取图像特征。

二、论文解读

 1、网络结构

VGGNet可以看成是加深版的AlexNet,把网络分成了5段,每段都把多个尺寸为3×3的卷积核串联在一起,每段卷积接一个尺寸2×2的最大池化层,最后面接3个全连接层和一个softmax层,所有隐层的激活单元都采用ReLU函数。

VGGNet包含很多级别的网络,深度从11层到19层不等。为了解决初始化(权重初始化)等问题,VGG采用的是一种Pre-training的方式,先训练浅层的的简单网络VGG11,再复用VGG11的权重初始化VGG13,如此反复训练并初始化VGG19,能够使训练时收敛的速度更快。比较常用的是VGGNet-16和VGGNet-19。VGGNet-16的网络结构如下图所示:

2、论文思路

用小的卷积核(3*3)不断来加深网络,评估在不同深度下对大规模图像识别中准确率。

      注:两个3*3的卷积核的感受野是相当于一个5*5的卷积核的感受野。

3、模型特点

  • 使用多个小卷积核构成的卷积层代替较大的卷积层,两个3x3卷积核的堆叠相当于5x5卷积核的视野,三个3x3卷积核的堆叠相当于7x7卷积核的视野。一方面减少参数,另一方面拥有更多的非线性变换,增加了CNN对特征的学习能力;
  • 引入1*1的卷积核,在不影响输入输出维度的情况下,引入更多非线性变换,降低计算量,​​​​​同时,还可以用它来整合各通道的信息,并输出指定通道数;
  • 训练时,先训练级别简单(层数较浅)的VGGNet的A级网络,然后使用A网络的权重来初始化后面的复杂模型,加快训练的收敛速度;
  • 训练时,先训练级别简单(层数较浅)的VGGNet的A级网络,然后使用A网络的权重来初始化后面的复杂模型,加快训练的收敛速度;
  • 采用Multi-Scale方法来做数据增强,增加训练的数据量,防止模型过拟合;
  • VGGNet不使用局部响应归一化(LRN),这种标准化并不能在ILSVRC数据集上提升性能,却导致更多的内存消耗和计算时间。

 

4、为什么两个3*3的卷积核的感受野是相当于一个5*5的卷积核的感受野?

      首先从单个3*3的卷积核的谁敢首页来进行靠拢,当我们使用一个3*3的卷积核时,此时它的感受野是3*3;当我们在上述3*3的卷积核的基础上再增加一个3*3卷积核时,此时两个连续3*3的卷积核的感受野变成了5*5,这是因为第二个3*3的卷积核考虑了第一个卷积核输出的3*3的区域,而此时这个区域在原始输入上对应5*5的区域。

5、用两个3*3的卷积核代替一个5*5的卷积核有什么作用?

        (1)减少参数的数量:

        使用两个3*3的卷积核的参数数量明显少于一个5*5的卷积核的参数数量。具体来说,两个3*3的卷积核总共有2*3*3=18个参数;而一个5*5的卷积核有5*5=25个参数,这就意味着使用两个较小的卷积核来代替一个较大的卷积核可以减少参数,从而减少计算的复杂度和模型过拟合的情况。

        下图展示了为什么“两个3x3卷积层”与“单个5x5卷积层”具有等效的5x5的感受野。

        (2)增加非线性:

       使用 2个3x3卷积层拥有比1个5x5卷积层更多的非线性变换(前者可以使用两次ReLU激活函数,而后者只有一次),使得卷积神经网络对特征的学习能力更强。意味着,我们将在这两个卷积层之间增加一个额外的非线性激活函数,这样不仅仅增加了模型的非线性表达能力。更能够使模型捕获更复杂的特征。 

        (3)减少网络层参数

  • ①对于两个3x3卷积核,所用的参数总量为2×32×channels2\times3^2\times{channels}2×32×channels​​​​​(假设通过padding填充保证卷积层输入输出通道数不变)
  • ②对于单个5x5卷积核,参数量为52×channels5^2\times{channels}52×channels​​​​​
  • ③参数量减少了(1−2×32×channels52×channels)×100%=28%(1-\frac{2\times3^2\times{channels}}{5^2\times{channels}})\times100\%=28\%(1−52×channels2×32×channels​)×100%=28%​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

6、1x1卷积核的作用(优势)

  • 作用1:不影响输入输出的维度情况下(即图片尺寸不变),降低了大量运算,同时改变了维度(通道数);
  • 作用2:卷积之后再紧跟ReLU进行非线性处理,提高决策函数的非线性

7、感受野的通用计算公式是什么?

       对于连续的卷积操作,其累积感受野的计算可以使用下述公式:

RF=k+(k-1)(n-1)

其中:

  • RF:是累积感受野的大小;
  • k:是每个卷积核的大小;
  • n:是连续卷积操作的数量。

8、为什么多层小的卷积核获得的感受野与单层较大的卷积核一致?

见下图,输入的8个元素可以视为feature map的宽或者高,当输入为8个神经元经过三层conv3x3的卷积得到2个神经元。三个网络分别对应stride=1,pad=0的conv3x3、conv5x5和conv7x7的卷积核在3层、1层、1层时的结果。因为这三个网络的输入都是8,也可看出2个3x3的卷积堆叠获得的感受野大小,相当1层5x5的卷积;而3层的3x3卷积堆叠获取到的感受野相当于一个7x7的卷积。

  • input=8,3层conv3x3后,output=2,等同于1层conv7x7的结果;
  • input=8,2层conv3x3后,output=2,等同于2层conv5x5的结果

或者说,三层的conv3x3的网络,最后两个输出中的一个神经元,可以看到的感受野相当于上一层是3,上上一层是5,上上上一层(也就是输入)是7。 

同时,倒着看网络,也就是反向传播过程,每个神经元相对于前一层甚至输入层的感受野大小也就意味着参数更新会影响到的神经元数目。在分割问题中卷积核的大小对结果有一定的影响,在上图三层的conv3x3中,最后一个神经元的计算是基于第一层输入的7个神经元,换句话说,反向传播时,该层会影响到第一层conv3x3的前7个参数。从输出层往回forward同样的层数下,大卷积影响(做参数更新时)到的前面的输入神经元越多。

三.结论

本文评估了深度卷积网络(到19层)在大规模图片分类中的应用。

结果表明:深度有益于提高分类的正确率。

How:通过在传统的卷积网络框架中使用更深的层能够在ImageNet数据集上取得优异的结果。

附录中,展示了我们的模型可以很好的泛化到更多数据集种,性能达到甚至超过了围绕较浅深度的图像表达建立的更复杂的识别流程。

我们的实验结果再次确认了深度在视觉表达中的重要性

四、VGGNet使用PyTorch框架实现

项目地址:VGGNet | Kaggle

import torch
from torch import nn
import sys
sys.path.append("../input/d2ld2l")
import d2l
from d2l.torch import load_data_fashion_mnist
from d2l.torch import train_ch6
from d2l.torch import try_gpu
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 = ((1,64),(1,128),(2,256),(2,512),(2,512))
def vgg(conv_arch, class_num):

    conv_layers = []
    in_channels = 1

    for (num_convs, out_channels) in conv_arch:
        conv_layer = vgg_block(num_convs, in_channels, out_channels)
        conv_layers.append(conv_layer)
        in_channels = out_channels

    return nn.Sequential(
        *conv_layers,
        nn.Flatten(),
        nn.Linear(out_channels * 7 * 7, 4096),
        nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 4096),
        nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 10)
    )
ratio = 4
small_conv_arch = [(v[0],v[1]//4) for v in conv_arch]
net = vgg(small_conv_arch,10)
lr,num_epochs,batch_size = 0.05,10,128
train_iter,test_iter = load_data_fashion_mnist(batch_size,resize = 244)
train_ch6(net,train_iter,test_iter,num_epochs,lr,try_gpu())

五、VGGNet使用keras框架实现

from keras.models import Sequential
from keras.layers import Conv2D, AveragePooling2D, Flatten, Dense, Activation, MaxPool2D, BatchNormalization, Dropout, ZeroPadding2D

1、VGG-16 (configuration D)

model = Sequential()

# first block
model.add(Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same',input_shape=(224,224, 3)))
model.add(Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))

# second block
model.add(Conv2D(filters=128, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(Conv2D(filters=128, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))

# third block
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))

# forth block
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))

# fifth block
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))

# sixth block (classifier)
model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000, activation='softmax'))

model.summary()

2、VGG-19 (configuration E)

vgg_19 = Sequential()

# first block
vgg_19.add(Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same',input_shape=(224,224, 3)))
vgg_19.add(Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(MaxPool2D((2,2), strides=(2,2)))

# second block
vgg_19.add(Conv2D(filters=128, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=128, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(MaxPool2D((2,2), strides=(2,2)))

# third block
vgg_19.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(MaxPool2D((2,2), strides=(2,2)))

# forth block
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(MaxPool2D((2,2), strides=(2,2)))

# fifth block
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same'))
vgg_19.add(MaxPool2D((2,2), strides=(2,2)))

# seventh block (classifier)
vgg_19.add(Flatten())
vgg_19.add(Dense(4096, activation='relu'))
vgg_19.add(Dropout(0.5))
vgg_19.add(Dense(4096, activation='relu'))
vgg_19.add(Dropout(0.5))
vgg_19.add(Dense(1000, activation='softmax'))

vgg_19.summary()

参考:

CNN经典网络模型(三):VGGNet简介及代码实现(PyTorch超详细注释版)_vggnet是哪年发明的_华科附小第一名的博客-CSDN博客

卷积神经网络VGG Net论文细读 - 幕布 (mubu.com)

【论文精读3】VGGNet——《Very Deep Convolutional Networks for Large-Scale Image Recognition》 - 知乎 (zhihu.com)

【论文阅读】《very deep convolutional networks for large-scale image recognition》 - 知乎 (zhihu.com)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1276204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Beta冲刺总结随笔

这个作业属于哪个课程软件工程A这个作业要求在哪里beta冲刺事后诸葛亮作业目标Beta冲刺总结随笔团队名称橘色肥猫团队置顶集合随笔链接Beta冲刺笔记-置顶-橘色肥猫-CSDN博客 文章目录 一、Beta冲刺完成情况二、改进计划完成情况2.1 需要改进的团队分工2.2 需要改进的工具流程 三…

【深度优先】LeetCode1932:合并多棵二叉搜索树

作者推荐 动态规划LeetCode2552:优化了6版的1324模式 题目 给你 n 个 二叉搜索树的根节点 ,存储在数组 trees 中(下标从 0 开始),对应 n 棵不同的二叉搜索树。trees 中的每棵二叉搜索树 最多有 3 个节点 &#xff0…

Linux 权限管理

1 Linux 安全模型 AAA认证资源分派: 当用户登录时,系统会自动分配令牌 token,包括用户标识和组成员等等信息 1.1 用户 Linux 中每个用户是通过 User ID(UID)来唯一标识的。 1.2 用户组 Linux 中可以将一个或者多个…

CentOS 部署 WBO 在线协作白板

1)WBO 白板工具介绍 1.1)WBO 白板简介 WBO 是一个自由和开源的在线协作白板。它允许多个用户同时在一个虚拟的大型白板上画图。该白板对所有线上用户实时更新,并且状态始终保持。它可以用于许多不同的目的,包括艺术、娱乐、设计和…

SQL Server 2016(创建数据表)

1、需求描述。 在名为“class”的数据库中创建表,表名称为“course”,其中要包含序号、课程、课程编号、学分、任课教师、上课地点、开始时间、结束时间、备注等列。 设置各个字段的数据类型。其中,"序号"列为标识列,从…

今日现货黄金最新建议

近期现货黄金价格再度逼近历史高位,很多本来在场外观望的投资者,都纷纷希望进场一试身手。然而大涨大跌的行情并不是很适合新手投资者参与,如果大家还没做好技术上的准备,可以多听听正规交易平台的专业人士的意见。 在正式入市之前…

TCP 重传、滑动窗口、流量控制、拥塞控制

1:重传机制 超时重传 快速重传 SACK 方法 Duplicate SACK 1:重传机制 超时重传:重传机制的其中一个方式,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的ACK确认应答报文…

(四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)

一、无人机模型简介: 单个无人机三维路径规划问题及其建模_IT猿手的博客-CSDN博客 参考文献: [1]胡观凯,钟建华,李永正,黎万洪.基于IPSO-GA算法的无人机三维路径规划[J].现代电子技术,2023,46(07):115-120 二、Tiki-taka算法(TTA&#xf…

3D开发引擎HOOPS在建筑工程行业中的应用与影响

Tech Soft 3D在工程图形方面的历史可以追溯到90年代初,从一开始,建筑和施工行业就存在于我们的DNA中。最初,Tech Soft 3D因现在的HOOPS Visualize技术被收购,并于1996年从Autodesk公司分离出来,作为Autodesk公司以建筑…

Drift plus penalty 漂移加惩罚Part2——性能分析

文章目录 正文Performance analysisAverage penalty analysis 平均惩罚分析Average queue size analysis 平均队列大小分析Probability 1 convergenceApplication to queues with finite capacityTreatment of queueing systemsConvex functions of time averages Delay tradeo…

AI产业前瞻报告:探讨GPTs背后的产业逻辑:拉开AIGC应用生态的帷幕

今天分享的是AI系列深度研究报告:《AI产业前瞻报告:探讨GPTs背后的产业逻辑:拉开AIGC应用生态的帷幕》。 (报告出品方:光大证券) 报告共计:13页 1、GPTs 拉开 AIGC 应用生态的帷幕 1.1、 Ope…

怎么让百度快速收录,百度SEO收录工具

百度收录对于一个网站的重要性不言而喻。拥有良好的百度收录意味着网站能够更好地被搜索引擎收录,为用户提供更精准的搜索结果。而怎样实现百度快速收录成为了许多网站管理员关注的焦点。 百度收录的重要性 百度是国内最大的搜索引擎之一,拥有数以亿计的…

成倍提高生产力工具Notion

成倍提高生产力工具Notion Notion已经成为了很多内容创作者的唯一生产力工具,甚至很多企业已经把Notion当作他们的唯一的工作平台,学习这款软件不仅能提高你的工作效率甚至在职场上也会成为一个吃香的技能,在美国有人制作销售Notion模板&…

Flink的部署模式和运行模式

集群角色 Flink提交作业和执行任务,需要几个关键组件: 客户端:代码由客户端获取并作转换,之后提交给Jobmanager Jobmanager就是Flink集群的管事人,对作业进行中央调度管理;当从客户端获取到转换过的作业后…

redis主从复制模式和哨兵机制

目录 第一章、主从复制模式1.1)Redis 主从复制模式介绍1.2)Redis 主从复制实现、 第二章、哨兵机制2.1)容灾处理之哨兵2.2)Sentinel 配置 第一章、主从复制模式 1.1)Redis 主从复制模式介绍 ①单点故障:数…

视频怎么去水印?如何下载保存无水印视频?

你是否曾经在观看鬼畜素材视频时,被烦人的水印挡住了视线,让你感到十分郁闷?不要担心,今天我将为你介绍几种经典的方法,让你轻松下载无水印视频,让观看体验更加清爽不留痕迹。让我们一起来试试吧&#xff0…

Android 断点调试

Android 调试 https://developer.android.google.cn/studio/debug?hlzh-cn 调试自己写的代码(不在Android源码) 点击 Attach debugger to Android process 图标 需要在添加断点界面手动输入函数名 但也可以不手动,有个技巧可以new 空proje…

springboot + vue 智能物流管理系统

qq(2829419543)获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:springboot 前端:采用vue技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件&#xf…

应用于智慧零售的AI边缘计算盒子+AI算法软硬一体化方案

中国是世界上最大的消费市场,零售行业拥有极大的发展潜力,阿里、腾讯两大互联网巨头正在加紧、加大布局; 信迈智慧零售方案可涵盖快消行业、服饰行业、餐饮行业、酒店行业、美家行业、消费电子行业、新零售商行业、服饰连锁、大卖场/商超、百…

CF1877 E. Autosynthesis 基环树dp

传送门:CF [前题提要]:一道基环树dp,但是题目有点绕,当时卡了我整整半天,到了第二天换了和清醒的脑子然后和别人讨论才整明白,故记录一下 题目很绕,故不再介绍. 首先对于这种下标和值有关系的题目.其实不难想到建图(CF上有大量这种 t r i c k trick trick),随便举个类似的题…