目录

前言

网络结构与配置

“积小成多”

VGG小套路

训练细节

实验结果讨论

Pytorch实现


前言

今天我们要来讨论的论文是《ImageNet Classification with Deep Convolutional Neural Networks》,其作者提出的AlexNet网络是ISLVRC 2012竞赛的冠军网络。这篇论文里有很多关于减少过拟合的做法,可以说是对深度卷积网络应用于图像分类任务的重大探索。


网络结构与配置

老规矩,先把VGGNet的结构图摆上来。其实VGGNet的配置有六种,深度和其他配置也逐渐升级,可以看下表,A的配置是最拉的,而E的配置是最豪华的。

 图片来自论文

而我们平时使用VGGNet时,一般都是使用D这个配置,也就是16层这个配置,下面是它的网络结构图。

 图片来自网络


“积小成多”

我们可以看到,VGGNet使用的卷积核都是3*3,不像AlexNet那些,起手就是11*11。那是因为这篇论文的作者使用了一些技巧。在讲这个技巧前,我们先讲讲感受野的概念,感受野其实就是卷积后,输入图上多少个格子映射为输出图上的一个格子,如下图。

 图片来自网络

最下面的图是5*5的尺寸,在经过3*3卷积核,步长为1的卷积后,输出了中间那张图,尺寸为3*3。也就是说原图的3*3映射为输出图上的1*1,所以感受野为3*3。而第二张图经过3*3卷积核卷积后,输出最顶上那张图,感受野也是3*3。

假如我们把第一张图看成输入图,最顶上那张图看作输出图,那么输入图上的5*5映射为了输出图上的1*1。所以说此时的感受野为5*5。可以看出,使用连续两层3*3的卷积,其感受野就为5*5

而VGGNet就是使用了这种方法。连续使用两层的感受野是5*5,连续使用三层就是7*7。

 图片来自论文

 图片来自论文

有的人可能要问,如果我要5*5的感受野,直接给个5*5的卷积核不就搞定了吗,为啥还要叠两层这么麻烦?

第一个原因就是这样叠几层可以多用几次激活函数。注意到上面的结构图,每个卷积层后面都跟着一个激活函数。如果我们叠加两层用3*3卷积核的卷积层,那么我们会使用两次激活函数。而如果我们只是使用一层5*5卷积核的卷积层,虽然感受野一样,但是只使用了一次激活函数。作者在文中提到,使用多次激活函数可以让决策函数更具区分性

第二个原因是这样做可以减少参数。假设我们叠两层3*3卷积核的卷积层,那么参数就是2*3*3=18,我们使用有同样感受野的单层5*5卷积核的卷积层,它的参数为5*5=25(这里假设通道一致,因此不加入计算,如果忘记如何计算可以看这篇)。很明显叠两层的参数比直接一层的参数要少。


VGG小套路

有我们上面提到的积小成多的方法,我们就可以疯狂叠这个组合了。值得注意的是,在两层卷积之后,我们的图像尺寸并没有发生变化,因为作者加了padding。我们可以简单计算一下:(224-3+2)/1+1=224。可以看成尺寸并没有变化。整张图的尺寸变化都是在池化层里。因此我们可以总结出VGGNet网络结构的一个套路。

首先图像输入,叠多个3*3卷积核的卷积层(每个卷积层后记得加激活函数ReLU),然后使用最大池化层缩小一半的尺寸(因为池化的核是2*2,步长是2),然后重复叠卷积和最大池化这个过程,当图像尺寸缩小到一定的程度,就可以把它扁平化,输入一个全连接网络了。全连接网络连接个三层,最后一层的神经元的数量设定为分类的数量便可以了。

但是这个套路并不是没有限制的,首先作者提到,当叠到19层后,网络的误差就饱和了,不能再下降了。除此之外,卷积核为3*3的卷积层也不可以叠太多,因为这样叠而尺寸不发生变化是由于我们加了padding,叠到后面,真正有效的数据都集中在中间一小部分,而周围都是我们加的padding,是无效信息,所以我们像VGGNet叠个两次或者三次就好了。


训练细节

这篇论文中关于训练的细节也挺有意思,我们也拿出来说说。首先作者在论文里提到,虽然它的网络更深,参数也更多,但是这个网络的收敛时间却比AlexNet少。为什么呢?其一是因为更大深度和更小的卷积核尺寸施加了隐式正则化,使网络需要更少的时间收敛。其二是因为使用了预初始化

我们重点看第二个原因。作者在论文中说:“网络权重的初始化非常重要,因为由于深度网络中梯度的不稳定性,不好的初始化可能会阻碍学习。”那么他是如何进行网络的初始化的呢

        由缓至急徐徐进

 图片来自论文

 图片来自论文

首先作者先训练个A配置的网络(请看上面的配置表),因为网络A的深度比较浅,可以通过随机初始化进行训练。训练完A配置后,再利用A的权重给其他配置的网络进行初始化。你可能会发现,其他配置有的层A没有啊,那怎么办?问题不大,A没有的层,我们就对它进行随机初始化。

当然这只是一个办法,后来作者发现其他人设计了一个初始化的方法,可以不用这样做预训练。


另外一个训练的细节是训练用的图像

首先我们要先设定一个尺寸S,这个S的设定有两个方法。第一个方法是直接设定为256或者384。第二个方法是在[256,512]这个区间里随机选一个。

得到这个尺寸S后,我们把图像的最短边缩小为S,长边跟着缩同样的幅度。比如说S是256,我有一张图片它是640*512,首先把短边512缩成256,也就是除二,因此长边640也要除二,变成320。所以最后是640*512变为320*256,我们叫这个是各向同性的缩放。放缩后,我们再从中间随机裁剪出224*224的图像来,再给它做一个随机水平翻转,随机RGB色移。


实验结果讨论

 图片来自论文

讨论一下结果。通过这个表格,我们可以看出,同一个网络配置之下,使用方法二确定S(作者称这个方法是尺寸抖动)来训练的结果错误率会更低

同时我们也看到,使用了LRN的错误率会更高,这也是为啥上一篇我提到有论文认为LRN没鬼用。

同时我们又看到,随着深度提高,错误率会越低,说明性能有所提升。同时还有个小细节,D的配置不使用方法二确定S时结果比E配置还好,所以这也是为什么平时使用D配置更多。

        注意:论文里还提到了多种测试方法,上图的结果为其中一种测试方法,但其实其他方法得到趋势和这个一样,所以就只拿这个出来讲。


Pytorch实现

说了这么多,我们照旧用Pytorch来实现一下VGGNet的D配置。

# 引入
import torch.nn as nn
import torchclass VGGNet(nn.Module):def __init__(self):super(VGGNet, self).__init__()self.features = nn.Sequential(nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),  # input[3, 224, 224]  output[64, 224, 224]nn.ReLU(inplace=True),nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),  # output[64, 224, 224]nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),                  # output[64, 112, 112]nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),  # output[128, 112, 112]nn.ReLU(inplace=True),nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),  # output[128, 112, 112]nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),                  # output[128, 56, 56]nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),  # output[256, 56, 56]nn.ReLU(inplace=True),nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),  # output[256, 56, 56]nn.ReLU(inplace=True),nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),  # output[256, 56, 56]nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),                  # output[256, 28, 28]nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),  # output[512, 28, 28]nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),  # output[512, 28, 28]nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),  # output[512, 28, 28]nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),                  # output[512, 14, 14]nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),  # output[512, 14, 14]nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),  # output[512, 14, 14]nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),  # output[512, 14, 14]nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),                  # output[512, 7, 7])self.classifier = nn.Sequential(nn.Dropout(p=0.5),nn.Linear(512*7*7, 4096),nn.ReLU(True),nn.Dropout(p=0.5),nn.Linear(4096, 4096),nn.ReLU(True),        nn.Linear(4096, 1000))def forward(self, x):x = self.features(x)x = torch.flatten(x, start_dim=1)x = self.classifier(x)return x

作者:公|众|号【荣仙翁】

内容同步在其中,想看更多内容可以关注我哦。

通俗学AI(3):VGG套路得人心相关推荐

  1. 通俗学AI(4):残差探索最深

    目录 前言 为何残差 何为残差 残差结构细节 网络结构 Pytorch实现 结果讨论 前言 今天我们要分享的论文是<Deep Residual Learning for Image Recogn ...

  2. 用python画笛卡尔心形线_05.总是套路得人心,如何用数学+Python示爱!

    接上题: 心里随便想一个数a,计算 ( ( a + 52.8 ) * 5 - 3.9343 ) * 2 - 10a ( ( a + 52.8 ) * 5 - 3.9343 ) * 2 - 10a = ...

  3. 自古深情留不住,总是套路得人心!带你吊打面试官...

    一.前言 自古深情留不住,总是套路得人心! 在我们的生活中,处处充满套路,事事都有潜规则.对于一切以利益为中心的职场来说,更是如此. 我相信每一个职场人都有自己的奋斗目标,谁也不愿意一辈子碌碌无为,但 ...

  4. 深情留不住,套路得人心- -聊聊套路那些事儿

    本文来自网易云社区 作者:朱蕊 本文来自于朱蕊在网易实践者沙龙分享[深情留不住,套路得人心- -聊聊套路那些事儿]的文字记录,全文7000字,阅读完成大概需要7分钟. 下午好~很高兴今天能跟大家一起来 ...

  5. 『跟着雨哥学AI』系列之六:趣味案例——基于U-Net的宠物图像分割

    点击左上方蓝字关注我们 课程简介: "跟着雨哥学AI"是百度飞桨开源框架近期针对高层API推出的系列课.本课程由多位资深飞桨工程师精心打造,不仅提供了从数据处理.到模型组网.模型训 ...

  6. 学AI哪家强?清华全球第1,Top5中有这3所中国高校

    来源:大数据(ID:hzdashuju) 本文约3000字,建议阅读5分钟. 本文介绍了全球院校计算机科学领域实力的排名情况. 日历牌又翻完了一年,2018年各种盘点和排行榜也尘埃落定.马萨诸塞大学计 ...

  7. Funny:还是程序猿会玩——弹幕炸天学AI和区块链,玩起来!弹慕君,你也值得拥有!

    Funny-程序猿的快乐之弹幕炸天学AI和区块链,玩起来!弹慕君,你也值得拥有! 导读 还是程序猿会玩--弹幕炸天学AI和区块链,玩起来!弹慕君,你也值得拥有! 视频观看:Funny程序猿的快乐之弹幕 ...

  8. 【AI白身境】学AI必备的python基础​​​​​​​

    文章首发于微信公众号<有三AI> [AI白身境]学AI必备的python基础 今天是新专栏<AI白身境>的第三篇,所谓白身,就是什么都不会,还没有进入角色. 上一篇给大家介绍了 ...

  9. 程序员,别逼自己学 AI 了,掌握正确的方法,开发水平暴增!

    今天,想跟大家聊聊 Python 人工智能. 最近几年,我看过市面上很多 Python和人工智能的教程,基本都是先介绍Python基本语法.dict.tuple 等基本库的使用,最后学习机器学习.深度 ...

最新文章

  1. 改名 Meta,打元宇宙牌,老龄化的 Facebook 能否再换新颜
  2. 《全球人工智能发展报告(2018)》发布:一览全球AI领域竞争态势
  3. abbyy在使用时提示更改分辨率如何处理
  4. PagerHelper-分页类
  5. 在bcb中添加activex控件_LinkedCell 属性介绍,OLEObjects 控件
  6. STL源码学习之空间配置
  7. 2.1、StopWatch 启动与停止(ok)
  8. what is the core technology for WEBGIS and MobileGIS
  9. DupeString 与 StringOfChar 的区别 - 回复 鹰@长空
  10. 拓端tecdat|R语言中的岭回归、套索回归、主成分回归:线性模型选择和正则化
  11. java日期互转:LocalDateTime、String、Instant、Date
  12. 函数极值最值凸性拐点渐近线总结
  13. Eclipse中如何clean项目以及clean的作用
  14. 2-PHP代码审计——PHPCMSV9.6.0 sql注入漏洞
  15. Android Camera2 教程 · 第三章 · 预览
  16. 笔试强训48天——day29
  17. 所谓“螺旋方阵”,是指对任意给定的N,将1到N×N的数字从左上角第1个格子开始,按顺时针螺旋方向顺序填入N×N的方阵里。本题要求构造这样的螺旋方阵。
  18. 怎么压缩gif图片大小?如何压缩gif又不影响画质
  19. 7-19 评委打分 (15 分)
  20. 数据保护新愿景:欧盟GDPR十个误解与争议

热门文章

  1. 禁用和恢复用户账户Linux,linux用户和组管理.ppt
  2. javaWeb基础二:Servlet(java前后端交互的技术)
  3. 各大网站软件提交入口 |软件发布
  4. Excel如何批量将文本型数值转为数值
  5. 有序的hashmap (linkedhashmap) 测试及原理
  6. uni-app微信小程序结合腾讯地图获取定位导航以及城市选择器
  7. python endwith_Python endswith()方法 - Python 教程 - 自强学堂
  8. vue keep-alive 缓存 不生效解决方案
  9. 我以为我喜欢编程是因为我喜欢你
  10. python如何比较大小_python列表如何比较大小