「七夕的礼物」: 一日搞懂卷积神经网络

今天我们要讲的是:「一日搞懂卷积神经网络」

  • 如果你需要 ppt,可以到 这里(Github) 或 这里 (Onedrive) 这里 (百度云) 下载
  • 如果你需要 code, 欢迎访问 这里
  • 往期写过的一些也许对你有帮助的文章,请来 这里
  • 深度学习的一些资料, 快来 这里
题目虽为 一日搞懂卷积神经网络,但我个人认为这对于一个刚入门的朋友来说并不是一件易事,更多的只是一个噱头罢了。由于篇幅的问题,ppt只有50页,想在这50页把所有的东西讲完,也不是一件易事,后文中的每一项技术,每一个架构,兴许都是一篇甚至多篇论文,都值得我们仔细研究一番。

有知友指出本文会对初学者造成误导,东西讲解不够透彻,我自我反思了一下,完全掌握这些内容也许需要1到2个月的时间,加之本人才学疏浅,不能很好地将细节表述清楚,故本文也许不太适合刚入门的朋友。
如果本文给您带来了困扰,我在此表示抱歉,它并没有起到如标题所述的能让您一日搞懂卷积神经网络。在此,感谢给我提出建议的知友,同时也希望在阅读本文时,各位知友能够有选择性的斟酌。


如果你是一名深度学习的初学者,强烈推荐你跟着 CS231n 走完一遍。
如果你是学完 CS231n 后再来看这份ppt,我相信你会有新的体会和见解。


1. 人工智能 — 就在我们身边

你一定记得,上古时期我们看过的《机械公敌》,《机器人总动员》,以及前几年的《模仿游戏》,《机械姬》,是的,这是人工智能,它就在我们身边。

你一定记得,上古时期的国际象棋AI深蓝,当然你也肯定知道,现在炽手可热的AlphaGo,冷扑大师,是的,这是人工智能,它就在我们身边。

你或许见过,无人驾驶的汽车,DeepMind 挑战 星际争霸2OpenAI 挑战Dota2,是的,这是人工智能,它就在我们身边。

2. 机器学习 — 好似寻找一个函数

我想,你会看到我的这篇文章,或是听到我的演讲,一定是对机器学习(深度学习)感兴趣。
什么是机器学习,从一个不精确的角度,它就如同寻找一个合适的函数

从小学开始,我们便一直和「函数」打交道,比如一条直线 f(x)=x+2
若输入为 x=3 ,很容易得到 f(3)=5
若输入为一段音频,你需要去模拟出一个类似与函数的东西,它的输出便是音频的内容
若输入为一个围棋盘面,你希望模拟一个复杂的函数,让它告诉你下一步该走哪里
若输入为一段,你希望模拟一个复杂的函数,让它像人一样和你进行交谈
是的,机器学习,如同寻找一个复杂的函数


3. 图像识别 — 深度学习入门

是的,我们今天要讲的,就是用卷积神经网络(CNN)来进行 「图像识别」。
假设今天我们已经有一个使用CNN搭建好的神经网路,我们把它叫做 f
那么我们向这个网络输入一张图片,通过复杂的计算,网络就会告诉你,这张图片是什么。


比如,我们的训练集(training data)是火影忍者的图片,那么自然,我们随意输入一张火影中角色的图片,网络模型便会告诉我们,他是谁! f(pic)=character
相反,如果我们输入一张不是火影角色的图片,那么网络模型便不能识别。


4. 卷积神经网络 — 让我们开始吧

卷积神经网络,前面有个卷积,自然,应该有个更简单的「东西」,
嗯,我们先来看 「神经网络(Neural Network)」

人工神经网络(Artificial Neural Networks,简写为ANNs)也简称为神经网络(NNs)或称作连接模型(Connection Model),它是一种模仿动物神经网络行为特征,进行分布式并行信息处理的算法数学模型。这种网络依靠系统的复杂程度,通过调整内部大量节点之间相互连接的关系,从而达到处理信息的目的。


我们使用圆圈来表示神经网络的输入。神经网络最左边的一层叫做 输入层(Input layer),最右的一层叫做 输出层(Output layer)。中间所有节点组成的一层叫做 隐藏层(Hidden layer),因为我们不能在训练样本集中观测到它们的值。
同时可以看到,下图的神经网络中有
「3个输入单元」,「4个隐藏单元 + 4个隐藏单元」 及一个「输出单元」。
我们把所有神经元都会和下一层的所有神经元相连的这种连接,叫做 全连接(Fully-connected layer)
图中的线,我们看做是权值(Weights),这个便是我们的神经网络需要训练的东西。
我相信你能懂下图中从左到右的前向计算。


所以我们主要来讲「反向传播算法」,这是一个困扰很多人的地方,
但是究其本质,就是「链式法则」。

需要从一个最简单的例子开始:
下图中,总共有 x,y,z 三个输入以及两个操作 +*
通过简单的前向传播,我们会得到
q=x+y=-1+5=4 f=z*q=2*4=8

接下来就是方向传播,我们需要分别求 \frac{\partial{f}}{\partial{x}} , \frac{\partial{f}}{\partial{y}} , \frac{\partial{f}}{\partial{z}}

f=q*z \rightarrow \frac{\partial{f}}{\partial{z}} =q=4,\frac{\partial{f}}{\partial{q}} =z=2,
q=x+y \rightarrow \frac{\partial{q}}{\partial{x}}=\frac{\partial{q}}{\partial{y}} =1
那么 \frac{\partial{f}}{\partial{x}}=\frac{\partial{f}}{\partial{q}}*\frac{\partial{q}}{\partial{x}}=z*1=2 ,\frac{\partial{f}}{\partial{y}}=\frac{\partial{f}}{\partial{q}}*\frac{\partial{q}}{\partial{y}}=z*1=2
我想你一定看到了,所有的一切,关键都在「链式法则 — Chain Rule」。


接下来,进入「卷积神经网络」,一个通常的卷积神经网络,是由「卷积层」「池化层」「全连接层」三种层进行组合而成的。


「全连接层」其实就是我们前面讲到的NN,我们直接来讲「卷积层 - convolutional layer」

以一张RGM图像为例,比如它的大小是 32\times32 ,因为它有三个通道(channel),所以我们的输入会是一个 32\times32\times3 的方块样子。
另外,我们也会有相对应的「卷积核 - filter」,用来进行卷积计算。
下图中,我们选用的是 5\times5 大小的卷积核,
这里需要特别注意,因为我们的输入是有3个通道,也就是「特征图 - feature map」有三张,所以我们的卷积核也要扩展到相同的 深度(depth),所以最后我们会有另外一个 5\times5\times3 的小方块。


卷积核在feature map上按照从左到右,从上到小的顺序依次扫过,最后得到 28\times28\times1 的特征图,你可以稍微想一下,为什么会是 28\times28 ,稍后给你答案。

嗯,原因就是,我们扫动的时候,「步长- stride」被设为 1 ,并且不向外侧进行「填充- padding」。
好,假设我们有 6 个卷积核,每一个卷积核和特征图进行卷积计算后,都会得到一张新的特征图,嗯,那最后我们就会得到一个 28\times28\times6 的新特征图。

这里我们有必要了解清楚 「步长- stride」 「填充- padding」。
下图很清晰地告诉你,一个卷积层,需要有输入,也就是特征图,
还要有四个参数,分别是 「步长- stride」,「填充- padding」,「卷积核的大小 - kernel size」, 「卷积核的数量- num of filters」
不同的参数,将会得到不同的新特征图。


另外一个重要的层是「池化层- pooling layer」,最常见的是「最大池化 - max pooling 」「平均池化 - average pooling 」。

池化层需要指定步长和卷积核的大小,下图的例子非常明了。


有了基本的这些层,我们就可以来构建自己的卷积神经网络了,
卷积层过后需要接一个激活函数,现在大家都用 ReLU 或者是它的变种了。我这里并不会展开讲各种激活函数,如果你有兴趣,可以自行查阅资料。
另外是一个叫做 flatten 的操作,简单来说就是把特征图摊平。


5. 卷积神经网络架构 — 从古到今的演变

好的,粗略地讲过了卷积神经网络,我们把目光跳转到一些经典的架构上。它们是:

毫无疑问,CNN之父Lecun开启了CNN的光明之路,它在1998年发明了具有时代意义的「LeNet 」,用来识别手写数字。
它的架构在如今看来,是算不上什么,但是在当时,是个创举。

真正在图像分类问题上有里程碑意义的是「AlexNet 」,它是2012年 ImageNet 的冠军之作

它首次使用了ReLU这个被后世广为流传的激活函数,并运用「权重衰变 - Weight Decay 」「Dropout 」来防止模型过拟合
值得一提的是,当时的GTX580只有3GB的内存,无法训练如此庞大的网络,所以它们使用了两张GPU进行分组训练,这也是后来「ResNeXt 」分组卷积想法的来源。

「Network in Network」,这个由新加坡国立大学设计的新型卷积神经网络架构,为后世多个优秀的网络架构的诞生提供了基础。

它提出了「Mlpconv layer」的概念,对后来「GoogLeNet」Inception「ResNet」Residual block,都有帮助。

它提出的「Global average pooling」,也被后世广泛运用。

「VGG Network」,牛津大学VGG实验室设计的架构,将AlexNet的8层提高到了19层,真正让深度这个词得以充分体现。
从VGG开始,人们不再使用太大的卷积核,取而代之的是若干个小卷积核的组合。
比如, 3 个步长为 13\times3 卷积核,可以拥有同 17\times7 的卷积核一样的感受野,
但是,它可以使整个网络变得更深,并且更具有非线性。
同时,还能够进一步减少训练的参数量。

关于参数的计算,有些朋友有一些疑惑,那么下图可以帮助你理解它是如何计算的。

我们要训练的参数其实就是卷积核的参数量,这和输入输出特征图数量以及卷积核本身的大小有关,希望下图的列子能够帮到你。

如果你理解了上图的列子,欢迎你再尝试自己计算一下VGG16的总参数量
值得一提的是,在训练的时候,因为有forward 和 backward,所以参数量要乘以 2
另外一个就是网络所需要的内存,这个也是非常重要的一个指标,因为当前的GPU内存空间非常有限。可以从下图得知,在网络最开始的几层,占用的GPU内存最多,而绝大多数的参数,都来自于全连接层,这也是一个后来全局池化被运用而全连接层被减少使用的原因。


「GoogLeNet」,到目前为止总共有四篇paper,如果你有兴趣,可以一一阅读,我今天,只讲最基本的模型。

从上图中网络整体架构可以看出,有一个大量重复的Inception,是的,这就是GoogLeNet的关键所在。

最开始,我们用的是被称为Naive Inception module的东东,但是一个相当严重的问题,它的参数量巨大,怎么办,于是,一个曾经在Network in Network被提出的 1\times1 的卷积核,就排上用场了,我们可以用它来减低或者增加维度,所以,我们得到了GoogLeNet第一版的Inception module,至于后来,这个Inception module又被修改了多次,篇幅问题,这里就不一一介绍了


「Residual Network」,何凯明聚聚亲情奉献的神一般的网络架构,横扫了2015年所有的classificationdetection 比赛并且都是碾压第二名。
同时这篇paper也是2016年CVPR best paper,当之无愧的有一个里程碑!

它将神经网络的深度提高到了一个新的高度——1000层,这是一个若干年前人们想都不敢想的数字,而使用「残差模块 - Residual Block」,也有效地避免了「梯度消失 - Vanishing Gradient」 的问题。
在理解的 残差模块 的时候,你会恍然大悟,确实,我们不拟合 H(x),而是拟合 F(x) ,确实能够让网络更容易学习。仔细看图中我举得例子,我们可以看到残差带来的好处。

把微小放大,化腐朽为神奇!

在网络不断加深的情况下,为了减小所要训练的参数量,作者又提出了一个与GoogLeNet有异曲同工之妙的Bottleneck,这样训练 3 层所需要的参数可以降低到与 2 层差不多,从而让网络不断加深成为可能。

另外,在作者发布第一篇paper后,他们又意识到恒等变换的重要性,随后又尝试更改了激活函数的位置,提出了「full pre-activation」的架构,再次提高了ResNet的精确度。


「Wide Residual Network」,我们叫它宽残差网络吧,是的,一直以来,网络都朝着深这个方向发展,但是似乎还有另外一个问题,那就是网络的宽度。
原本的ResNet,可以用瘦长来形容,而本篇paper,作者提出了不一味地加深网络,而是在加深的同时也加宽,即在每一层使用更多的卷积核。

效果果然出奇地好,它超过了原本的ResNet,均衡发展,才是好孩子,哈哈?


「ResNeXt Network」,你以为就到此结束了吗?没有的。凯明聚聚们,在ResNet之后,又推出了新的架构ResNeXt 。提高模型的准确率,目前主要的策略是将网络加深或加宽,但是随着超参数数量的增加,网络设计的难度和计算开销也会增加。
在本文中,作者提出了一个新的概念「cardinality 」,他们认为,增加 cardinality 比增加深度和宽度更有效。事实证明,这又是一次成功的改进!


「DenseNet」,这是 CVPR2017 的best paper,从最开始的plain layers,到后来的Residual block,现在又一次被升级为了「Dense block」
何为Dense block?在Dense block内部,每一层都将作为后面剩下的所有层的输入,这样,原本 l 层的网络,连线数量将变为 \frac{l(l+1)}{2} ,这样,梯度的传播方式,由线性变成树状反向,减少了梯度消失的可能,有利于更深层网络的训练。


「Dual Path Networks」,这是今年7月份被放在arxiv上的paper,它做了什么事?
它把ResNet 和 DenseNet进行了结合!!

模型看起来略微复杂了一点,如果有机会或者有时间,再另开一片博文来写一下吧

当然,它的结果,超过了以往所有的网络,截至目前,可以称得上 State of the art


6. 训练技巧 — 你需要一点魔法

是的,我们很快地看过了经典的一些卷积神经网络架构,现在,我们来谈一下在训练的时候有什么应该注意的技巧。


「Pre-Processing」,数据预处理,这是一件容易做而且行之有效的方法,常见的有如下两种。「-mean/std」应该是我最常用的。


「Data Augmentation」,数据增强,为了增加训练集(training set)的资料量和提高模型的泛化能力,我们常常在训练的时候使用数据增强技术,旋转,翻转,平移,裁剪等等,你可以从下图中进行感性认识。


「Weight Initialization」,权值的初始化,这个是非常重要的,现在比较推荐的是凯明聚聚的He's Weight Initial


「Regularization」,正规化,我们可以使用一些正规化的方法,来防止模型过拟合,Weight Decay Dropout,恐怕你不能再熟悉了吧


「Fine-tune」,微调,我们可以使用已经训练好的weight,然后稍加修改最后一层的softmax,进行retrain,我们可以冻结网络的一层或者若干层,从而使得我们在很短的时间内就训练出一个能够适用于我们自己的 「资料集 - data set」 的模型。



7. 最后的总结 — 结束仅仅是新的开始

是的,ILSVRC 一路走来,造就了众多优秀的神经网络架构,如今,或许比赛将不会继续,但是,人类智慧的结晶,仍在不断发光!
让我们简要总结一下今天的内容吧!


8. 写在最后 — 分享,让世界更美妙

我是一名 CS 硕士一年级的学生,水平有限,分享这个PPT纯粹是希望给大家一点启示。
如果您发现我有任何地方写错或是写得不对,请不吝赐教!
倘若我的文章能够给您一丁点帮助,我便心满意足了!

您可以随意转载我的文章,只要注明 作者 和 出处 即可。
我不会向任何人收取任何费用,这是纯粹的分享,知识是无价的。

如果您愿意给我点个赞,我就很开心了!

编辑于 2018-03-03

文章被以下专栏收录