卷积神经网络常见架构AlexNet、ZFNet、VGGNet、GoogleNet和ResNet模型

目前的常见的卷积网络结构有AlexNet、ZF Net、VGGNet、GoogleNet、ResNet等等,接下来我们对这些架构一一详解。

LeNet-5

LeNet-5模型诞生于1998年,是Yann LeCun教授在论文Gradient-based learning applied to document recognition中提出的,它是第一个成功应用于数字识别问题的卷积神经网络,麻雀虽小五脏俱全,它包含了深度学习的基本模块:卷积层,池化层,全连接层。是其他深度学习模型的基础。
LeNet模型结构:C层表示卷积层;S层是一个池化层
LeNet除了输入层,总共有7层。输入是32*32大小的图像
- C1是卷积层,卷积层的过滤器尺寸大小为5*5,深度为6,不使用全0补充,步长为1,所以这一层的输出尺寸为32-5+1=28,深度为6。
- S2层是一个池化层,这一层的输入是C1层的输出,是一个28*28*6的结点矩阵,过滤器大小为2*2,步长为2,所以本层的输出为14*14*6
- C3层也是一个卷积层,本层的输入矩阵为14*14*6,过滤器大小为5*5,深度为16,不使用全0补充,步长为1,故输出为10*10*16
- S4层是一个池化层 ,输入矩阵大小为10*10*16,过滤器大小为2*2,步长为2,故输出矩阵大小为5*5*16
- C5层是一个卷积层,过滤器大小为5*5,和全连接层没有区别,这里可看做全连接层。输入为5*5*16矩阵,将其拉直为一个长度为5*5*16的向量,即将一个三维矩阵拉直到一维向量空间中,输出结点为120。
- F6层是全连接层 ,输入结点为120个,输出结点为84个
- 输出层也是全连接层,输入结点为84个,输出节点个数为10。

# coding=utf-8
import tensorflow as tf
from tensorflow.contrib.layers import flatten


# 定义LeNet网络
def LeNet(input_tensor):
    # C1  conv  Input=32*32*1, Output=28*28*6
    conv1_w = tf.Variable(tf.truncated_normal(shape=[5, 5, 1, 6], mean=0, stddev=0.1))
    conv1_b = tf.Variable(tf.zeros(6))
    conv1 = tf.nn.conv2d(input_tensor, conv1_w, strides=[1, 1, 1, 1], padding='VALID')+conv1_b
    conv1 = tf.nn.relu(conv1)

    # S2 Pooling Input=28*28*6 Output=14*14*6
    pool_1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')

    # C3 conv Input=14*14*6 Output=10*10*6
    conv2_w = tf.Variable(tf.truncated_normal(shape=[5, 5, 6, 16], mean=0, stddev=0.1))
    conv2_b = tf.Variable(tf.zeros(16))
    conv2 = tf.nn.conv2d(pool_1, conv2_w, strides=[1, 1, 1, 1], padding='VALID')+conv2_b
    conv2 = tf.nn.relu(conv2)

    # S4 Pooling Input=10*10*6 OutPut=5*5*16
    pool_2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')

    # Flatten Input=5*5*16 Output=400
    fc1 = flatten(pool_2)

    # C5 conv Input=5*5*16=400 Output=120
    fc1_w = tf.Variable(tf.truncated_normal(shape=(400, 120), mean=0, stddev=0.1))
    fc1_b = tf.Variable(tf.zeros(120))
    fc1 = tf.matmul(fc1, fc1_w) + fc1_b

    # F6 Input=120 OutPut=84
    fc2_w = tf.Variable(tf.truncated_normal(shape=(120, 84), mean=0, stddev=0.1))
    fc2_b = tf.Variable(tf.zeros(84))
    fc2 = tf.matmul(fc1, fc2_w)+fc2_b
    fc2 = tf.nn.relu(fc2)

    # F7 Input=84  Output=10
    fc3_w = tf.Variable(tf.truncated_normal(shape=(84, 10), mean=0, stddev=0.1))
    fc3_b = tf.Variable(tf.zeros(10))
    logits = tf.matmul(fc2, fc3_w) + fc3_b
    return logits

gitHub上代码:使用LeNet-5和类LeNet-5网络识别手写字体

AlexNet

LeNet提出并成功地应用手写数字识别,但是很快,CNN的锋芒被SVM和手工设计的局部特征所掩盖。2012年,AlexNet在ImageNet图像分类任务竞赛中获得冠军,一鸣惊人,从此开创了深度神经网络空前的高潮。论文ImageNet Classification with Deep Convolutional Neural Networks
AlexNet优势在于:
- 使用了非线性激活函数ReLU(如果不是很了解激活函数,可以参考我的另一篇博客 激活函数Activation Function
- 提出了LRN(Local Response Normalization),局部响应归一化,LRN一般用在激活和池化函数后,对局部神经元的活动创建竞争机制,使其中响应比较大对值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力
- 使用CUDA加速深度神经卷积网络的训练,利用GPU强大的并行计算能力,处理神经网络训练时大量的矩阵运算
- 在CNN中使用重叠的最大池化,AlexNet全部使用最大池化。AlexNet中提出让步长比池化核的尺寸小,这样池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。
- 使用数据增广(data agumentation)和Dropout防止过拟合。【数据增广】随机地从256*256的原始图像中截取224*224大小的区域,相当于增加了2048倍的数据量;【Dropout】AlexNet在后面的三个全连接层中使用Dropout,随机忽略一部分神经元,以避免模型过拟合。
ALexNet模型架构
AlexNet总共包含8层,其中有5个卷积层和3个全连接层,有60M个参数,神经元个数为650k,分类数目为1000
1. 第一层输入图像规格为227*227*3,过滤器(卷积核)大小为11*11*3,深度为96,步长为4,则卷积后的输出为55*55*96,分成两组,进行池化运算处理,过滤器大小为3*3,步长为2,池化后的每组输出为27*27*48
2. 第二层的输入为27*27*96,分成两组,为27*27*48,填充为2,过滤器大小为5*5*48,深度为128,步长为1,则每组卷积后的输出为27*27*128;然后进行池化运算,过滤器大小为3*3,步长为2,则池化后的每组输出为13*13*128
3. 第三层两组中每组的输入为13*13*128,填充为1,过滤器尺寸为3*3*256,深度为192,步长为1,卷积后输出为13*13*192。在C3这里做了通道的合并,也就是一种串联操作,所以一个卷积核卷积的不再是单张显卡上的图像,而是两张显卡的图像串在一起之后的图像,所以卷积核的厚度为256,这也是为什么图上会画两个3*3*128的卷积核。
4. 第四层两组中每组的输入为12*13*192,填充为1,过滤器尺寸为3*3*192,深度为192,步长为1,卷积后输出为13*13*192
5. 第五层输入为上层的两组13*13*192,填充为1,过滤器大小为3*3*192,深度为128,步长为1,卷积后的输出为13*13*128;然后进行池化处理,过滤器大小为3*3,步长为2,则池化后的每组输出为6*6*128
6. 第六层为全连接层,上一层总共的输出为6*6*256,所以这一层的输入为6*6*256,采用6*6*256尺寸的过滤器对输入数据进行卷积运算,每个过滤器对输入数据进行卷积运算生成一个结果,通过一个神经元输出,设置4096个过滤器,所以输出结果为4096
7. 第六层的4096个数据与第七层的4096个神经元进行全连接
8. 第八层的输入为4096,输出为1000(类别数目)

ZF Net

ZF论文 Visualizing and Understanding Convolutional Networks 最大的贡献在于通过使用可视化技术揭示了神经网络各层到底在干什么,起到了什么作用
可视化技术依赖于反卷积操作,即卷积的逆过程,将特征映射到像素上。具体过程如下图所示:
- Unpooling:在卷积神经网络中,最大池化是不可逆的,作者采用近似的实现,使用一组转换变量switch 记录每个池化区域最大值的位置。在反池化的时候,将最大值返回到其所应该在的位置,其他位置用0补充。
- Rectification:反卷积的时候也同样利用ReLU激活函数
- Filtering:解卷积网络中利用卷积网络中相同的filter的转置应用到Rectified Unpooled Maps。也就是对filter进行水平方向和垂直方向的翻转。
卷积和反卷积
可视化不仅能够看到一个训练完的模型的内部操作,而且还能够帮助改进网络结构从而提高网络性能。ZFNet模型是在AlexNet基础上进行改动,网络结构上并没有太大的突破。差异表现在, AlexNet是用两块GPU的稀疏连接结构,而ZFNet只用了一块GPU的稠密链接结构;改变了AleNet的第一层,将过滤器的大小由11*11变成7*7,并且将步长由4变成2,使用更小的卷积核和步长,保留更多特征;将3,4,5层变成了全连接。
ZF Net架构

VGG Net

VGG模型是牛津大学VGG组提出的。论文为Very Deep Convolutional Networks for Large-Scale Image Recognition VGG全部使用了3*3的卷积核和2*2最大池化核通过不断加深网络结构来提神性能。采用堆积的小卷积核优于采用大的卷积核,因为多层非线性层可以增加网络深层来保证学习更复杂的模式,而且所需的参数还比较少。
- 两个堆叠的卷积层(卷积核为3*3)有限感受野是5*5,三个堆叠的卷积层(卷积核为3*3)的感受野为7*7,故可以堆叠含有小尺寸卷积核的卷积层来代替具有大尺寸的卷积核的卷积层,并且能够使得感受野大小不变,而且多个3*3的卷积核比一个大尺寸卷积核有更多的非线性(每个堆叠的卷积层中都包含激活函数),使得decision function更加具有判别性。
- 假设一个3层的3*3卷积层的输入和输出都有C channels,堆叠的卷积层的参数个数为 3 × ( 3 2 C 2 ) = 27 C 2 ,而等同的一个单层的7*7卷积层的参数为 7 2 C 2 = 49 C 2
VGG网络的架构
可以看到VGG-D使用了一种块结构:多次重复使用统一大小的卷积核来提取更复杂和更具有表达性的特征。VGG系列中,最多使用是VGG-16,下图来自Andrew Ng深度学习里面对VGG-16架构的描述。如图所示,在VGG-16的第三、四、五块:256、512、512个过滤器依次用来提取复杂的特征,其效果就等于一个带有3各卷积层的大型512*512大分类器。
这里写图片描述

GoogleNet

GoogLeNet论文为Going deeper with Convolutions
提高深度神经网络性能最直接的办法是增加它们尺寸,不仅仅包括深度(网络层数),还包括它的宽度,即每一层的单元个数。但是这种简单直接的解决方法存在两个重大的缺点,更大的网络意味着更多的参数,使得网络更加容易过拟合,而且还会导致计算资源的增大。经过多方面的思量,考虑到将稀疏矩阵聚类成相对稠密子空间来倾向于对稀疏矩阵的优化,因而提出inception结构。
Inception架构的主要思想是考虑怎样用容易获得密集组件近似覆盖卷积视觉网络的最优稀疏结构。Inception模型的基本结构如下,在多个不同尺寸的卷积核上同时进行卷积运算后再进行聚合,并使用1*1的卷积进行降维减少计算成本。传统的卷集层的输入数据只和一种尺寸的卷积核进行运算,输出固定维度的特征数据(例如128),而在Inception模块中,输入和多个尺寸的卷积核(1*1,3*3和5*5)分别进行卷积运算,然后再聚合,输出的128特征中包括1*1卷积核的 a 1 个输出特征,3*3卷积核的 a 2 个输出特征和5*5卷积核的 a 3 个输出特征 ( a 1 + a 2 + a 3 = 128 ) 。Inception结构将相关性强的特征汇聚在一起,同样是128个输出特征,Inception得到的特征“冗余”的信息比较少,所以收敛速度就会更快。
Inception基本结构
GoogleNet采用9个Inception模块化的结构,共22层,除了最后一层的输出,其中间结点的分类效果也很好。还使用了辅助类结点(auxiliary classifiers),将中间某一层的输出用作分类,并按一个较小的权重加到最终分类结果中。这样相当于做了模型融合,同时给网络增加了反向传播的梯度信号,也提供了额外的正则化,对于整个网络的训练大有益处。下图是网络的结构图:
GoogleNet结构
注:每一个Inception结构模块包含两层

ResNet

论文Deep Residual Learning for Image Recognition
随着网络的加深,出现了训练集准确率下降,错误率上升的现象,就是所谓的“退化”问题。按理说更深的模型不应当比它浅的模型产生更高的错误率,这不是由于过拟合产生的,而是由于模型复杂时,SGD的优化变得更加困难,导致模型达不到好的学习效果。ResNet就是针对这个问题应运而生的。
ResNet,深度残差网络,基本思想是引入了能够跳过一层或多层的“shortcut connection”,如下图所示,即图中的“弯弯的弧线”。ResNet中提出了两种mapping:一种是identity mapping,另一种是residual mapping。最后的输出为y=F(x)+x,顾名思义,identity mapping指的是自身,也就是x,而residual mapping,残差,指的就是y-x=F(x)。这个简单的加法并不会给网络增加额外的参数和计算量,同时却能够大大增加模型的训练速度,提高训练效果,并且当模型的层数加深时,这个简单的结构能够很好的解决退化问题。
残差块
有两种基础的残差块的设计如下图:
这里写图片描述
这两种结构是分别针对ResNet34和ResNet50/101/152,右边的“bottleneck design”要比左边的“building block”多了1层,增添1*1的卷积目的就是为了降低参数的数目,减少计算量。所以浅层次的网络,可使用“building block”,对于深层次的网络,为了减少计算量,bottleneck desigh 是更好的选择。
再将x添加到F(x)中,还需考虑到x的维度与F(x)维度可能不匹配的情况,论文中给出三种方案:
A: 输入输出一致的情况下,使用恒等映射,不一致的情况下,则用0填充(zero-padding shortcuts)
B: 输入输出一致时使用恒等映射,不一致时使用 projection shortcuts
C: 在两种情况下均使用 projection shortcuts
经实验验证,虽然C要稍优于B,B稍优于A,但是A/B/C之间的稍许差异对解决“退化”问题并没有多大的贡献,而且使用0填充时,不添加额外的参数,可以保证模型的复杂度更低,这对更深的网络非常有利的,因此方法C被作者舍弃。
最后,放出一张图片展示常见的ResNet网络架构的组成,如下所示:
这里写图片描述

总结

  • LeNet是第一个成功应用于手写字体识别的卷积神经网络 ALexNet展示了卷积神经网络的强大性能,开创了卷积神经网络空前的高潮
  • ZFNet通过可视化展示了卷积神经网络各层的功能和作用
  • VGG采用堆积的小卷积核替代采用大的卷积核,堆叠的小卷积核的卷积层等同于单个的大卷积核的卷积层,不仅能够增加决策函数的判别性还能减少参数量
  • GoogleNet增加了卷积神经网络的宽度,在多个不同尺寸的卷积核上进行卷积后再聚合,并使用1*1卷积降维减少参数量
  • ResNet解决了网络模型的退化问题,允许神经网络更深

猜你喜欢

转载自blog.csdn.net/weixin_42111770/article/details/80719302