关注上方深度学习技术前沿”,选择“星标公众号”

资源干货,第一时间送达!

【导读】本文是卷积神经网络结构系列专题第三篇文章,前面我们先后介绍了LeNet和AlexNet。本篇博文将介绍一下在ImageNet 2014 年斩获目标定位竞赛的第一名,图像分类竞赛的第二名的网络结构---VGG。VGG 是 Visual Geometry Group 的缩写,是这个网络创建者的队名,作者来自牛津大学。

实验室地址:http://www.robots.ox.ac.uk/~vgg/

VGG论文

VGG 最大的特点就是它在之前的网络模型上,通过比较彻底地采用 3x3 尺寸的卷积核来堆叠神经网络,从而加深整个神经网络的层级。并且VGG论文给出了一个非常振奋人心的结论:卷积神经网络的深度增加和小卷积核的使用对网络的最终分类识别效果有很大的作用。

VGG网络结构

VGG 选择的是在 AlexNet 的基础上加深它的层数,但是它有个很显著的特征就是持续性的添加 3x3 的卷积核。而AlexNet 有 5 层卷积层,从上面的网络结构图我们可以看出来,VGG 就是针对这 5 层卷积层进行改造,共进行了 6 种配置。

下面是这六种配置的效果展示图:

从上面的效果图中,我们发现VGG19是最好的。但是,VGG-19 的参数比 VGG-16 的参数多了好多。由于VGG-19需要消耗更大的资源,因此实际中VGG-16使用得更多。而且VGG-16网络结构十分简单,并且很适合迁移学习,因此至今VGG-16仍在广泛使用,下面我们主要来讨论一下VGG16的网络结构:

VGG16的网络结构

从上图可以看到网络的第一个卷积层的通道数为,然后每一层Max Pooling之后卷积层的通道数都成倍的增加,最后界三个全连接层完成分类任务。总的来说VGGNet的贡献可以概括如下两点:

  • 所有隐藏层都使用了ReLU激活函数,而不是LRN(Local Response Normalization),因为LRN浪费了更多的内存和时间并且性能没有太大提升。

  • 使用更小的卷积核和更小的滑动步长。和AlexNet相比,VGG的卷积核大小只有和两种。卷积核的感受野很小,因此可以把网络加深,同时使用多个小卷积核使得网络总参数量也减少了。

VGG的创新点

1. 使用3x3卷积核替代7x7卷积核,这样做的好处是:

  • 3x3 卷积核是能够感受到上下、左右、重点的最小的感受野尺寸。并且,2 个 3x3 的卷积核叠加,它们的感受野等同于 1 个 5x5 的卷积核,3 个叠加后,它们的感受野等同于 1 个 7x7 的效果。

  • 由于感受野相同,3个3x3的卷积,使用了3个非线性激活函数,增加了非线性表达能力,使得分割平面更具有可分性。

  • 使用3x3卷积核可以减少参数,假设现在有 3 层 3x3 卷积核堆叠的卷积层,卷积核的通道是 C 个,那么它的参数总数是 3x(3Cx3C) = 27C^2 。同样和它感受野大小一样的一个卷积层,卷积核是 7x7 的尺寸,通道也是 C 个,那么它的参数总数就是 49C^2。而且通过上述方法网络层数还加深了。三层3x3的卷积核堆叠参数量比一层7x7的卷积核参数链还要少。

  • 总的来说,使用3x3卷积核堆叠的形式,既增加了网络层数又减少了参数量。

最初应用 1x1 卷积核的神经网络是 Network In Network。使用1x1卷积核的主要好处:

  1. 增加网络的深度,使用多个1x1卷积核,在保持feature map 尺寸不变(即不损失分辨率)的前提下,可以大幅增加非线性表达能力,把网络做得很deep。

  2. 进行卷积核通道数的降维和升维。

  3. 实现跨通道的交互和信息整合。

总结就是:1x1 卷积核的好处是不改变感受野的情况下,进行升维和降维,同时也加深了网络的深度。

详细的介绍请见:【基础积累】1x1卷积到底有哪些用处?

基于Pytorch的VGG代码实现

class VGG16(torch.nn.Module):def __init__(self, num_classes):super(VGG16, self).__init__()# calculate same padding:# (w - k + 2*p)/s + 1 = o# => p = (s(o-1) - w + k)/2self.block_1 = nn.Sequential(nn.Conv2d(in_channels=3,out_channels=64,kernel_size=(3, 3),stride=(1, 1),# (1(32-1)- 32 + 3)/2 = 1padding=1),nn.ReLU(),nn.Conv2d(in_channels=64,out_channels=64,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2),stride=(2, 2)))self.block_2 = nn.Sequential(nn.Conv2d(in_channels=64,out_channels=128,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=128,out_channels=128,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2),stride=(2, 2)))self.block_3 = nn.Sequential(nn.Conv2d(in_channels=128,out_channels=256,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=256,out_channels=256,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=256,out_channels=256,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=256,out_channels=256,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2),stride=(2, 2)))self.block_4 = nn.Sequential(nn.Conv2d(in_channels=256,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=512,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=512,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=512,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2),stride=(2, 2)))self.block_5 = nn.Sequential(nn.Conv2d(in_channels=512,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=512,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=512,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.Conv2d(in_channels=512,out_channels=512,kernel_size=(3, 3),stride=(1, 1),padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2),stride=(2, 2)))self.classifier = nn.Sequential(nn.Linear(512*2*2, 4096),nn.ReLU(),nn.Linear(4096, 4096),nn.ReLU(),nn.Linear(4096, num_classes))for m in self.modules():if isinstance(m, torch.nn.Conv2d):#n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels#m.weight.data.normal_(0, np.sqrt(2. / n))m.weight.detach().normal_(0, 0.05)if m.bias is not None:m.bias.detach().zero_()elif isinstance(m, torch.nn.Linear):m.weight.detach().normal_(0, 0.05)m.bias.detach().detach().zero_()def forward(self, x):x = self.block_1(x)x = self.block_2(x)x = self.block_3(x)x = self.block_4(x)x = self.block_5(x)logits = self.classifier(x.view(-1, 512*2*2))probas = F.softmax(logits, dim=1)return logits, probas

参考链接:

1. https://blog.csdn.net/briblue/article/details/83792394

2. https://blog.csdn.net/briblue/article/details/83151475

3. https://blog.csdn.net/whz1861/article/details/78111606

重磅!DLer-计算机视觉交流群已成立!

欢迎各位Cver加入计算机视觉微信交流大群,本群旨在交流图像分类、目标检测、点云/语义分割、目标跟踪、机器视觉、GAN、超分辨率、人脸检测与识别、动作行为/时空/光流/姿态/运动、模型压缩/量化/剪枝、NAS、迁移学习、人体姿态估计等内容。更有真实项目需求对接、求职内推、算法竞赛、干货资讯汇总、行业技术交流等,欢迎加群交流学习!

进群请备注:研究方向+地点+学校/公司+昵称(如图像分类+上海+上交+小明)

广告商、博主请绕道!

???? 长按识别添加,邀请您进群!

原创不易,在看鼓励!比心哟!

【卷积神经网络结构专题】经典网络结构之VGG(附代码实现)相关推荐

  1. DeepLearning tutorial(5)CNN卷积神经网络应用于人脸识别(详细流程+代码实现)

    DeepLearning tutorial(5)CNN卷积神经网络应用于人脸识别(详细流程+代码实现) @author:wepon @blog:http://blog.csdn.net/u012162 ...

  2. 关系抽取:图卷积网络的学习(二)(附代码)

    关系抽取:图卷积网络的学习(二)(附代码) 目录 关系抽取:图卷积网络的学习(二)(附代码) 论文一:基于关系图的实体关系联合抽取 摘要 1.Introduction 2.Motivation 3.G ...

  3. 深度学习实战——利用卷积神经网络对手写数字二值图像分类(附代码)

    系列文章目录 深度学习实战--利用卷积神经网络对手写数字二值图像分类(附代码) 目录 系列文章目录 前言 一.案例需求 二.MATLAB算法实现 三.MATLAB源代码 参考文献 前言 本案例利用MA ...

  4. 卷积神经网络模型之——GoogLeNet网络结构与代码实现

    文章目录 GoogLeNet网络简介 GoogLeNet网络结构 Inception之前的几层结构 Inception结构 Inception3a模块 Inception3b + MaxPool In ...

  5. 利用Python实现十大经典排序算法(附代码流程)

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 作者:hustcc 来源:https://github.com/hustcc/JS ...

  6. 十大经典排序算法(附代码、动画及改进方案)

    前言说明 十大排序算法可以说是每个程序员最早接触的也是最重要的算法,这一块必须要非常熟练的掌握,应该要理解每种排序的思想,对各个排序的性能的了解也是基础且重要的.为了方便自己和大家学习,决定整合成一篇 ...

  7. 【NLP相关】NLP领域经典论文汇总(附代码实现)

    ❤️觉得内容不错的话,欢迎点赞收藏加关注

  8. 中移动Oracle,Oracle中国移动经典面试题(附代码跟两种答案)

    /* 中国移动sql面试题: create table test( id number(10) primary key, type number(10) , t_id number(10), valu ...

  9. 【卷积神经网络结构专题】一文详解AlexNet(附代码实现)

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! [导读]本文是卷积神经网络结构系列专题第二篇文章,前面我们已经介绍了第一个真正意义 ...

最新文章

  1. 嵌入式linux mono,嵌入式linux/android alsa_aplay alsa_amixer命令行用法(示例代码)
  2. 【转】C++ win32窗口创建详解
  3. 央视315曝光SDK事件,应用开发者如何避坑?
  4. 值得使用的CSS库添加图像悬停效果!
  5. sql还原数据库备份数据库_有关数据库备份,还原和恢复SQL面试问题–第一部分
  6. 【渝粤教育】国家开放大学2018年秋季 0056-22T知识产权法 参考试题
  7. 2021年PMP考试模拟题8(含答案解析)
  8. 华为h12m03装系统_华为H22H-03服务器怎么设置从U盘装系统
  9. VBScript详解(一)
  10. 那些年我们踩过的坑——Java中Date夏令时日期转换不一致问题
  11. Package pdftex.def Error: PDF mode expected, but DVI mode detected!
  12. 百度地图marker标注上如何加上数字
  13. linux驱动:二、LED灯驱动编写
  14. phpinfo()函数 写法
  15. Python爬虫系列之爬取某奢侈品小程序店铺商品数据
  16. 12.19 - 每日一题 - 408
  17. Exynos4412 移植针对Samsung的Linux-6.1(二)SD卡驱动——解决无法挂载SD卡的根文件系统
  18. 【YOLO学习笔记——数据集】之一YOLO数据集制作2
  19. 什么是网络营销 和网上销售是否一样
  20. 外包人员:互联网公司【二等公民】...

热门文章

  1. Nginx(5)-nginx.conf文件详解
  2. Receive本地下载安装方法
  3. 【解题报告】【HDOJ1233】【最小生成树】还是畅通工程
  4. linux下使用inotify实时监控文件变更,做完整性检查
  5. SQL安装时出现“以前的某个程序安装已在安装计算机上创建挂起的文件操作。运作安装程序之前必须重新启动计算机”...
  6. lisp提取长方形坐标_求修改lisp程序,如何提取CAD中多个点的坐标,(本人想提取UCS坐标系)另外只需要提取X,Y值,不要Z...
  7. python count()方法
  8. 命名实体识别NER 如何使用BERT实现
  9. 类的包访问权限:《Java编程思想》中一段话的困惑
  10. 网络设备转发数据包的整个流程_网络工程师(33):路由转发工作原理