Diving Into Popular CNN Varieties gaunthan Posted on Dec 15 2017 ? Deep Learning ? ? Machine Learning ? ? Image Classification ? ? Computer Vision ? ## Outline - LeNet, 1986 - AlexNet, 2012 - GoogLeNet, 2014 - VGG, 2014 - ResNet, 2015 ## LeNet 下图是由Yann LeCun在1998年设计的用于识别手写数字的CNN结构图,该网络被称为LeNet-5[^LeNet]: [^LeNet]:[LeNet-5 Paper: Comparison of Learning Algorithms for Handwritten Digit Recognition](http://yann.lecun.com/exdb/publis/pdf/lecun-95b.pdf)  Tensorflow代码实现可以看[这里](https://github.com/tensorflow/models/blob/master/research/slim/nets/lenet.py)或[这里](https://www.tensorflow.org/get_started/mnist/pros#build_a_multilayer_convolutional_network)。 其中网络结构定义代码如下所示: ```py def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') x_image = tf.reshape(x, [-1, 28, 28, 1]) W_conv1 = weight_variable([5, 5, 1, 32]) b_conv1 = bias_variable([32]) h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) h_pool1 = max_pool_2x2(h_conv1) W_conv2 = weight_variable([5, 5, 32, 64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1 , W_conv2) + b_conv2) h_pool2 = max_pool_2x2(h_conv2) h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64]) W_fc1 = weight_variable([7 * 7 * 64, 1024]) b_fc1 = bias_variable([1024]) h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) keep_prob = tf.placeholder("float") h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) W_fc2 = weight_variable([1024, 10]) b_fc2 = bias_variable([10]) y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) ``` **卷积层(也适合池化层)的输出尺寸可以通过以下公式计算:** $$ \lfloor\frac{W - F + 2P}{S}\rfloor + 1, W = 输入尺寸, F = 过滤器尺寸, P = 填充数量, S = 步幅 $$ 因为填充是图像的四周填充,故需要乘以2。 在CNN中有一个很重要的概念:感受野。感受野是指某层feature map的一个像素映射回原图的区域,即它感受到的区域。计算方式如下:  *(图片来自:[A guide to receptive field arithmetic for Convolutional Neural Networks](https://medium.com/mlreview/a-guide-to-receptive-field-arithmetic-for-convolutional-neural-networks-e0f514068807))* 下面逐层进行讲解: - INPUT 输入层:32x32的灰度值矩阵。 - C1 卷积层:输入尺寸为32,过滤器尺寸为5,填充为0,步幅为1,因此该层的输出尺寸为$ \frac{32 - 5 + 0}{1} + 1 = 28 $。一个卷积核有5*5个连接参数,加上1个偏置,共26个参数。C1层共有26*6=156个训练参数,有156*28*28*6=122304个连接。 - S2 池化层:输入尺寸为28,池化尺寸为2,填充为0,步幅为2,因此该层的输出尺寸为$ \frac{28 - 2 + 0}{2} + 1 = 14 $。 - C3 卷积层:输入尺寸为14,过滤器尺寸为5,填充为0,步幅为1,因此该层的输出尺寸为$ \frac{14 - 5 + 0}{1} + 1 = 10 $。 - S4 池化层:输入尺寸为10,池化尺寸为2,填充为0,步幅为2,因此该层的输出尺寸为$ \frac{10 - 2 + 0}{2} + 1 = 5 $。 - C5 卷积层:由于S4层输出尺寸为5,与卷积核的大小相同,所以卷积后形成的图的大小为1x1。这里形成120个卷积结果,每个都与上一层的16个图相连,所以在上图中就用"Full connection"描述了。 - F6 全连接层。F6层有84个节点,对应于一个7x12的比特图,-1表示白色,1表示黑色,这样每个符号的比特图的黑白色就对应于一个编码。  - OUTPUT 输出层。输出层也是全连接层,共有10个节点,分别代表数字0到9,且如果节点i的值为 0,则网络识别的结果是数字i。采用的是径向基函数(RBF)的网络连接方式。该层有84x10=840个设定的参数和连接。 池化用的都是最大池。池化层直接把图像的尺寸减半,使得参数的数量大大减少。 LeNet-5识别数字3的过程如下图所示:  ## AlexNet AlexNet[^AlexNet]的网络结构如下图所示: [^AlexNet]:[AlexNet Paper: ImageNet Classification with Deep Convolutional Neural Networks](https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf)  整个网络有8个需要训练的层, 前5个为卷积层,最后3层为全连接层。注意前面五层卷积层分成了上下两部分,它们在不同的GPU上进行训练,以此加快模型的训练过程。 Tensorflow代码看[这里](https://github.com/tensorflow/models/blob/master/research/slim/nets/alexnet.py)或[这里](https://github.com/kratzert/finetune_alexnet_with_tensorflow/blob/master/alexnet.py)。 AlexNet的创新点有: - 使用**ReLU**作为激活函数,解决了sigmoid在网络较深时引起的[梯度消失(gradient vanishing)问题](http://www.cnblogs.com/maybe2030/p/6336896.html)。 - 训练时使用**Dropout**随机忽略一部分神经元,避免模型过拟合。在AlexNet中主要是最后几个全连接层使用了Dropout。 - 在CNN中使用重叠的**最大池化**。此前CNN中普遍使用平均池化,AlexNet全部使用最大池化,避免平均池化的模糊化效果。并且AlexNet中提出让步长比池化核的尺寸小,这样池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。 - 提出了**LRN**层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。 LRN后来被研究者(VGG论文)发现并没有多大用处,现在已经没有什么模型使用LRN了,大多使用Batch Normalization(BN)。 ## GoogLeNet GoogLeNet[^GoogleNet]证明了一件事:用更多的卷积,更深的层次可以得到更好的结果。它的网络结构如下图所示: [^GoogleNet]:[GoogLeNet Paper: Going Deeper with Convolutions](https://www.cs.unc.edu/~wliu/papers/GoogLeNet.pdf)  为了避免梯度消失,网络额外增加了2个辅助的softmax用于向前传导梯度。文章中说这两个辅助的分类器的loss应该加一个衰减系数,但看caffe中的model也没有加任何衰减。此外,实际测试的时候,这两个额外的softmax会被去掉。 GoogLeNet层次虽然比较深,但结构其实很简单——经过前面几层卷积和池化层后,便是一直在重复一种称为Inception的结构:  Inception把输入一分四,做一些不同的卷积操作,最终再堆叠feature map。Softmax0之前经过了4个Inception,继续往下到Softmax1经过了3个,最后到达Softmax2经过了2个。4+3+2=9,整个网络总共有9个Inception。它的优点如下: - 简单:网络包含9个同样又相关的简单块 - 并行:Inception内部的4条通路是并行的 - 计算性能高、内存使用高效。网络是并行嵌套实现的,这要求更少的内存以及借助于并行机制可以更快的计算结果。GooLeNet仅27Mb大小(npy format),而且它的执行速度在普通硬件上也快于VGG和ResNet。 GoogLeNet给我们的一个启示是,多个不同的小卷积层的组合效果要优于单个大的卷积层,而且参数数量也更少。 实现代码请看[这里](https://lexiondebug.blob.core.windows.net/mlmodel/models/googlenet.py)或[这里](https://github.com/da-steve101/googlenet/blob/master/googlenet_model.py)。 ## VGG VGG[^VGG]是最符合典型CNN的一种网络,它在AlexNet的基础上加深了网络,以达到更好的效果。VGG也是5个group的卷积、2层fc图像特征、一层fc分类特征。根据前5个卷积group,每个group中的不同配置,VGG论文中给出了A~E这五种配置,卷积层数从8到16递增。 [^VGG]:[VGG Paper: VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION](https://arxiv.org/pdf/1409.1556.pdf) VGG 的一个关键是使用很多有着相对小的 kernel(3×3)的卷积层然后接上一个池化层,之后再将这个模块重复多次。 网络结构配置如下:  结构特点: 1. 小过滤器的尺寸为3x3 - 3x3是最小的能够捕获上下左右和中心的感受野,多个3x3的卷积层比一个大尺寸的卷积层具备更多非线性,使得预测函数能够更好拟合数据。 - 在步长为1的情况下, 两个3∗3的滤波器的最大感受野区域是5∗5, 三个3∗3的滤波器的最大感受野区域是7∗7,可以替代更大的滤波器尺寸。 2. 1x1过滤器 - 作用是在不影响输入输出维数的情况下,对输入线进行线性形变,然后通过Relu进行非线性处理,增加网络的非线性表达能力。 尽管VGG比AlexNet有更多的参数,更深的层次;但是VGG需要很少的迭代次数就开始收敛。这是因为: - 深度和小的过滤器尺寸起到了隐式的规则化的作用 - 一些层的pre-initialization - 由于存在大量的ReLU函数,不好的权值初始值对于网络训练影响较大。为了解决这个问题,先通过随机的方式训练最浅的网络A;然后在训练其他网络时,把A的前4个卷基层和最后全连接层的权值当做其他网络的初始值,未赋值的中间层通过随机初始化。 ## ResNet ResNet(Deep Residual Learning)[^ResNet]是2015年的ImageNet比赛冠军,可以说它将卷积用到了极致。除了使用更多层和更多的卷积,它的特殊在在于设计了"bottleneck"这样的block结构。该结构构成如下图所示: [^ResNet]:[Deep Residual Learning for Image Recognition](https://arxiv.org/pdf/1512.03385.pdf)  与VGGNet类似,ResNet也有几种配置方案,最深的Model达到了152层:  下图展示了34层配置时的网络结构:  从结构上来说,这个模型比前面几种都要简单,连LRN这样的层都没有。 ResNet的Tensorflow实现请看[这里](https://github.com/tensorflow/models/blob/master/official/resnet/resnet_model.py)或[这里](https://github.com/da-steve101/googlenet/blob/master/googlenet_model.py)。 ## References - [深度学习方法(五):卷积神经网络 CNN 经典模型整理 Lenet,Alexnet,Googlenet,VGG,Deep Residual Learning](http://blog.csdn.net/xbinworld/article/details/45619685) - [卷积神经网络的网络结构——以 LeNet-5 为例](http://blog.csdn.net/strint/article/details/44163869) - [AlexNet 原理及 Tensorflow 实现](http://blog.csdn.net/taoyanqi8932/article/details/71081390) - [深度学习的局部响应归一化 LRN(Local Response Normalization) 理解](http://blog.csdn.net/yangdashi888/article/details/77918311) - [simshang's blog - VGGNet](http://simtalk.cn/2016/09/25/VGGNet/) - [GoogLeNet系列解读](http://blog.csdn.net/shuzfan/article/details/50738394) - [GoogLeNet 学习心得](http://www.cnblogs.com/Allen-rg/p/5833919.html) - [卷积神经网络 - 动手学深度学习0.6文档](https://zh.gluon.ai/chapter_convolutional-neural-networks/index.html) 赏 Wechat Pay Alipay Linux 设置 Rime 默认英文状态 Linux 为 Nvidia 显卡安装闭源驱动