深度学习:卷积神经网络CNN入门

作者:机器之心
链接:https://www.zhihu.com/question/52668301/answer/131573702
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


Part 1:图像识别任务


卷积神经网络,听起来像是计算机科学、生物学和数学的诡异组合,但它们已经成为计算机视觉领域中最具影响力的革新的一部分。神经网络在 2012 年崭露头角,Alex Krizhevsky 凭借它们赢得了那一年的 ImageNet 挑战赛(大体上相当于计算机视觉的年度奥林匹克),他把分类误差记录从 26% 降到了 15%,在当时震惊了世界。自那之后,大量公司开始将深度学习用作服务的核心。Facebook 将神经网络用于自动标注算法、谷歌将它用于图片搜索、亚马逊将它用于商品推荐、Pinterest 将它用于个性化主页推送、Instagram 将它用于搜索架构。

<img src="https://i-blog.csdnimg.cn/blog_migrate/24ce2458dfefaf03f5fefe1c6eb1d5f9.jpeg" data-rawwidth="640" data-rawheight="249" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-834043be6a015ef9d7cf04de0cf03cca_r.jpg">

然而,应用这些网络最经典最流行的案例是进行图像处理。在图像处理任务中,让我们看一下如何使用卷积神经网络进行图像分类。


问题空间


图像分类是对输入图像的操作,最终输出一组最好地描述了图像内容的分类(如猫、狗等)或分类的概率。对人类来说,识别是打出生便开始学习的技能之一,对成人来说更是信手拈来,毫不费力。我们只需一眼便能快速识别我们所处的环境以及环绕在我们身边的物体。当我们看到一张图片或是环看四周的时候,无需刻意观察,多数时候也能立即描述出场景特征并标记出每一个对象。快速识别不同模式、根据早前知识进行归纳、以及适应不同的图像环境一直都是人类的专属技能,机器尚未享有。

<img src="https://i-blog.csdnimg.cn/blog_migrate/b2014be90d4cf5376511259d681a8f9c.jpeg" data-rawwidth="636" data-rawheight="222" class="origin_image zh-lightbox-thumb" width="636" data-original="https://pic3.zhimg.com/v2-a4552450f9ca496886c48cdd44475cce_r.jpg">

输入与输出


当计算机看到一张图像(输入一张图像)时,它看的是一大堆像素值。根据图片的分辨率和尺寸,它将看到一个 32 x 32 x 3 的数组(3 指代的是 RGB 值)。为了讲清楚这一点,假设我们有一张 JPG 格式的 480 x 480 大小的彩色图片,那么它对应的数组就有 480 x 480 x 3 个元素。其中每个数字的值从 0 到 255 不等,其描述了对应那一点的像素灰度。当我们人类对图像进行分类时,这些数字毫无用处,可它们却是计算机可获得的唯一输入。其中的思想是:当你提供给计算机这一数组后,它将输出描述该图像属于某一特定分类的概率的数字(比如:80% 是猫、15% 是狗、5% 是鸟)。


我们想要计算机做什么


现在我们知道了问题所在以及输入与输出,就该考虑如何处理了。我们想要计算机能够区分开所有提供给它的图片,以及搞清楚猫猫狗狗各自的特有特征。这也是我们人类的大脑中不自觉进行着的过程。当我们看到一幅狗的图片时,如果有诸如爪子或四条腿之类的明显特征,我们便能将它归类为狗。同样地,计算机也可以通过寻找诸如边缘和曲线之类的低级特点来分类图片,继而通过一系列卷积层级建构出更为抽象的概念。这是 CNN(卷积神经网络)工作方式的大体概述,下面是具体细节。


生物学连接


首先介绍些背景。当你第一次听到卷积神经网络这一术语,可能会联想到神经科学或生物学,那就对了。可以这样说。CNN 的确是从视觉皮层的生物学上获得启发的。视觉皮层有小部分细胞对特定部分的视觉区域敏感。Hubel 和 Wiesel 于 1962 年进行的一项有趣的试验详细说明了这一观点,他们验证出大脑中的一些个体神经细胞只有在特定方向的边缘存在时才能做出反应(即放电)。例如,一些神经元只对垂直边缘兴奋,另一些对水平或对角边缘兴奋。Hubel 和 Wisesl 发现所有这些神经元都以柱状结构的形式进行排列,而且一起工作才能产生视觉感知。这种一个系统中的特定组件有特定任务的观点(视觉皮层的神经元细胞寻找特定特征)在机器中同样适用,这就是 CNN 的基础。


结构


回到细节上来。更为详细的 CNN 工作概述指的是你挑一张图像,让它历经一系列卷积层、非线性层、池化(下采样(downsampling))层和完全连接层,最终得到输出。正如之前所说,输出可以是最好地描述了图像内容的一个单独分类或一组分类的概率。如今,难点在于理解其中每一层的工作方法。我们先来看最重要的部分。


第一层——数学部分


CNN 的第一层通常是卷积层(Convolutional Layer)。首先需要了解卷积层的输入内容是什么。如上所述,输入内容为一个 32 x 32 x 3 的像素值数组。现在,解释卷积层的最佳方法是想象有一束手电筒光正从图像的左上角照过。假设手电筒光可以覆盖 5 x 5 的区域,想象一下手电筒光照过输入图像的所有区域。在机器学习术语中,这束手电筒被叫做过滤器(filter,有时候也被称为神经元(neuron)或核(kernel)),被照过的区域被称为感受野(receptive field)。过滤器同样也是一个数组(其中的数字被称作权重或参数)。重点在于过滤器的深度必须与输入内容的深度相同(这样才能确保可以进行数学运算),因此过滤器大小为 5 x 5 x 3。现在,以过滤器所处在的第一个位置为例,即图像的左上角。当筛选值在图像上滑动(卷积运算)时,过滤器中的值会与图像中的原始像素值相乘(又称为计算点积)。这些乘积被加在一起(从数学上来说,一共会有 75 个乘积)。现在你得到了一个数字。切记,该数字只是表示过滤器位于图片左上角的情况。我们在输入内容上的每一位置重复该过程。(下一步将是将过滤器右移 1 单元,接着再右移 1 单元,以此类推。)输入内容上的每一特定位置都会产生一个数字。过滤器滑过所有位置后将得到一个 28 x 28 x 1 的数组,我们称之为激活映射(activation map)或特征映射(feature map)。之所以得到一个 28 x 28 的数组的原因在于,在一张 32 x 32 的输入图像上,5 x 5 的过滤器能够覆盖到 784 个不同的位置。这 784 个位置可映射为一个 28 x 28 的数组。


<img src="https://i-blog.csdnimg.cn/blog_migrate/7794e716e66e84a57fe904e15c412079.jpeg" data-rawwidth="640" data-rawheight="347" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-790a3d600c6b6208f3c7db27c393a1ea_r.jpg">

(注意:包括上图在内的一些图片来自于 Micheal Nielsen 的 「神经网络与深度学习( Neural Networks and Deep Learning)」一书。我强烈推荐这本书。这本书可免费在线浏览:Neural networks and deep learning


当我们使用两个而不是一个 5 x 5 x 3 的过滤器时,输出总量将会变成 28 x 28 x 2。采用的过滤器越多,空间维度( spatial dimensions)保留得也就越好。数学上而言,这就是卷积层上发生的事情。


第一层——高层次角度


不过,从高层次角度而言卷积是如何工作的?每个过滤器可以被看成是特征标识符( feature identifiers)。这里的特征指的是例如直边缘、原色、曲线之类的东西。想一想所有图像都共有的一些最简单的特征。假设第一组过滤器是 7 x 7 x 3 的曲线检测器。(在这一节,为了易于分析,暂且忽略该过滤器的深度为 3 个单元,只考虑过滤器和图像的顶层层面。)作为曲线过滤器,它将有一个像素结构,在曲线形状旁时会产生更高的数值(切记,我们所讨论的过滤器不过是一组数值!)

<img src="https://pic4.zhimg.com/50/v2-4e15bce4b402176ce8c6dca1538836d7_hd.png" data-rawwidth="624" data-rawheight="278" class="origin_image zh-lightbox-thumb" width="624" data-original="https://pic4.zhimg.com/v2-4e15bce4b402176ce8c6dca1538836d7_r.png">

左图:过滤器的像素表示;右图:曲线检测器过滤器的可视化;对比两图可以看到数值和形状的对应


回到数学角度来看这一过程。当我们将过滤器置于输入内容的左上角时,它将计算过滤器和这一区域像素值之间的点积。拿一张需要分类的照片为例,将过滤器放在它的左上角。

<img src="https://pic2.zhimg.com/50/v2-a7a8f5b74d66f7b5389f9c17a1417c09_hd.png" data-rawwidth="640" data-rawheight="227" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-a7a8f5b74d66f7b5389f9c17a1417c09_r.png">切记,我们要做的是将过滤器与图像的原始像素值相乘。切记,我们要做的是将过滤器与图像的原始像素值相乘。

<img src="https://pic4.zhimg.com/50/v2-f1c852e5da0df5407565aa5b0f78fe43_hd.png" data-rawwidth="640" data-rawheight="241" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-f1c852e5da0df5407565aa5b0f78fe43_r.png">

左图:感受野的可视化;右图:感受野的像素表示 * 过滤器的像素表示


简单来说,如果输入图像上某个形状看起来很像过滤器表示的曲线,那么所有点积加在一起将会得出一个很大的值!让我们看看移动过滤器时会发生什么。

<img src="https://pic4.zhimg.com/50/v2-4c637624f3f01ba910736784547c37db_hd.png" data-rawwidth="640" data-rawheight="224" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-4c637624f3f01ba910736784547c37db_r.png">

这个值小了很多!这是因为图像的这一部分和曲线检测器过滤器不存在对应。记住,这个卷积层的输出是一个激活映射(activation map)。因此,在这个带有一个过滤器卷积的例子里(当筛选值为曲线检测器),激活映射将会显示出图像里最像曲线的区域。在该例子中,28 x 28 x 1 的激活映射的左上角的值为 6600。高数值意味着很有可能是输入内容中的曲线激活了过滤器。激活地图右上角的值将会是 0,因为输入内容中没有任何东西能激活过滤器(更简单地说,原始图片中的这一区域没有任何曲线)。这仅仅是一组检测右弯曲线的过滤器。还有其它检测左弯曲线或直线边缘的过滤器。过滤器越多,激活映射的深度越大,我们对输入内容的了解也就越多。


声明:我在本小节中描绘的过滤器(filter)只是为了描述卷积中的数学过程。在下图中你可以看到训练后的网络中第一个卷积层的过滤器的实际可视化。尽管如此,主要观点仍旧不变。当在输入内容中寻找特定特征时,第一层上的过滤器在输入图像上进行卷积运算和「激活」(即计算高数值)。


<img src="https://i-blog.csdnimg.cn/blog_migrate/8b65495b3982312e2170c1925a7d9e15.jpeg" data-rawwidth="270" data-rawheight="277" class="content_image" width="270">

上图来自于斯坦福大学由 Andrej Karpathy 和 Justin Johnson 授课的 CS 231N 课程,推荐给渴望更深层理解 CNN 的人们:CS231n: Convolutional Neural Networks for Visual Recognition


网络中的更深处


在传统卷积神经网络架构中,卷积层之间还有其它类型的层。我强烈建议有兴趣的人阅读和它们有关的材料,并理解相应的功能和作用;但总的来说,它们提供的非线性和维度保留有助于提高网络的稳健性(robustness)并控制过拟合。一个典型的 CNN 结构看起来是这样的:


<img src="https://pic4.zhimg.com/50/v2-afa8132cdb9958051f102657335ac68f_hd.png" data-rawwidth="639" data-rawheight="46" class="origin_image zh-lightbox-thumb" width="639" data-original="https://pic4.zhimg.com/v2-afa8132cdb9958051f102657335ac68f_r.png">

输入→卷积→ReLU→卷积→ReLU→池化→ReLU→卷积→ReLU→池化→全连接


我们稍后再来讨论关键的最后一层,先回顾一下学到了哪些。我们讨论了过滤器是如何在第一个卷积层检测特征的。它们检测边缘和曲线一类的低级特征。正如想象的那样,为了预测出图片内容的分类,网络需要识别更高级的特征,例如手、爪子与耳朵的区别。第一个卷积层的输出将会是一个 28 x 28 x 3 的数组(假设我们采用三个 5 x 5 x 3 的过滤器)。当我们进入另一卷积层时,第一个卷积层的输出便是第二个卷积层的输入。解释这一点有些困难。第一层的输入是原始图像,而第二卷积层的输入正是第一层输出的激活映射。也就是说,这一层的输入大体描绘了低级特征在原始图片中的位置。在此基础上再采用一组过滤器(让它通过第 2 个卷积层),输出将是表示了更高级的特征的激活映射。这类特征可以是半圆(曲线和直线的组合)或四边形(几条直线的组合)。随着进入网络越深和经过更多卷积层后,你将得到更为复杂特征的激活映射。在网络的最后,可能会有一些过滤器会在看到手写笔迹或粉红物体等时激活。如果你想知道更多关于可视化卷积网络中过滤器的内容,可以查看 Matt Zeiler 和 Rob Fergus 的一篇讨论该问题的颇为杰出的研究论文。在 YouTube 上,Jason Yosinski 有一段视频十分视觉化地呈现了这一过程(如下)。有趣的是,越深入网络,过滤器的感受野越大,意味着它们能够处理更大范围的原始输入内容(或者说它们可以对更大区域的像素空间产生反应)。


完全连接层


检测高级特征之后,网络最后的完全连接层就更是锦上添花了。简单地说,这一层处理输入内容(该输入可能是卷积层、ReLU 层或是池化层的输出)后会输出一个 N 维向量,N 是该程序必须选择的分类数量。例如,如果你想得到一个数字分类程序,如果有 10 个数字,N 就等于 10。这个 N 维向量中的每一数字都代表某一特定类别的概率。例如,如果某一数字分类程序的结果矢量是 [0 .1 .1 .75 0 0 0 0 0 .05],则代表该图片有 10% 的概率是 1、10% 的概率是 2、75% 的概率是 3、还有 5% 的概率是 9(注:还有其他表现输出的方式,这里只展示了 softmax 的方法)。完全连接层观察上一层的输出(其表示了更高级特征的激活映射)并确定这些特征与哪一分类最为吻合。例如,如果该程序预测某一图像的内容为狗,那么激活映射中的高数值便会代表一些爪子或四条腿之类的高级特征。同样地,如果程序测定某一图片的内容为鸟,激活映射中的高数值便会代表诸如翅膀或鸟喙之类的高级特征。大体上来说,完全连接层观察高级特征和哪一分类最为吻合和拥有怎样的特定权重,因此当计算出权重与先前层之间的点积后,你将得到不同分类的正确概率。

<img src="https://i-blog.csdnimg.cn/blog_migrate/a4c26c8f94c1e7b9a0bde1e161f15461.jpeg" data-rawwidth="640" data-rawheight="206" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-0d4e7aabbd235461330da8904cd20bb5_r.jpg">

训练(也就是:什么能让其有效)


下面是神经网络中的一个我尚未提及但却最为重要的部分。阅读过程中你可能会提出许多问题。第一卷积层中的滤波器是如何知道寻找边缘与曲线的?完全连接层怎么知道观察哪些激活图?每一层级的滤波器如何知道需要哪些值?计算机通过一个名为反向传播的训练过程来调整过滤器值(或权重)。


在探讨反向传播之前,我们首先必须回顾一下神经网络工作起来需要什么。在我们刚出生的时候,大脑一无所知。我们不晓得猫啊狗啊鸟啊都是些什么东西。与之类似的是 CNN 刚开始的时候,权重或过滤器值都是随机的。滤波器不知道要去寻找边缘和曲线。更高层的过滤器值也不知道要去寻找爪子和鸟喙。不过随着年岁的增长,父母和老师向我们介绍各式各样的图片并且一一作出标记。CNN 经历的便是一个介绍图片与分类标记的训练过程。在深入探讨之前,先设定一个训练集,在这里有上千张狗、猫、鸟的图片,每一张都依照内容被标记。下面回到反向传播的问题上来。


反向传播可分为四部分,分别是前向传导、损失函数、后向传导,以及权重更新。在前向传导中,选择一张 32×32×3 的数组训练图像并让它通过整个网络。在第一个训练样例上,由于所有的权重或者过滤器值都是随机初始化的,输出可能会是 [.1 .1 .1 .1 .1 .1 .1 .1 .1 .1],即一个不偏向任何数字的输出。一个有着这样权重的网络无法寻找低级特征,或者说是不能做出任何合理的分类。接下来是反向传播的损失函数部分。切记我们现在使用的是既有图像又有标记的训练数据。假设输入的第一张训练图片为 3,标签将会是 [0 0 0 1 0 0 0 0 0 0]。损失函数有许多种定义方法,常见的一种是 MSE (均方误差)。

<img src="https://pic2.zhimg.com/50/v2-1d99155e7d28ecc87c9207e1ec845e5d_hd.png" data-rawwidth="472" data-rawheight="63" class="origin_image zh-lightbox-thumb" width="472" data-original="https://pic2.zhimg.com/v2-1d99155e7d28ecc87c9207e1ec845e5d_r.png">假设变量 L 等同该数值。正如所料,前两张训练图片的损失将会极高。现在,我们直观地想一下。我们想要预测标记(卷积网络的输出)与训练标记相同(意味着网络预测正确)。为了做到这一点,我们想要将损失数量最小化。将其视为微积分优化问题的话,也就是说我们想要找出是哪部分输入(例子中的权重)直接导致了网络的损失(或错误)。假设变量 L 等同该数值。正如所料,前两张训练图片的损失将会极高。现在,我们直观地想一下。我们想要预测标记(卷积网络的输出)与训练标记相同(意味着网络预测正确)。为了做到这一点,我们想要将损失数量最小化。将其视为微积分优化问题的话,也就是说我们想要找出是哪部分输入(例子中的权重)直接导致了网络的损失(或错误)。

<img src="https://pic3.zhimg.com/50/v2-8920aa91f987f9b43c61d6755331e006_hd.png" data-rawwidth="640" data-rawheight="222" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-8920aa91f987f9b43c61d6755331e006_r.png">

这是一个 dL/dW 的数学等式,W 是特定层级的权重。我们接下来要做的是在网络中进行后向传导,测定出是哪部分权重导致了最大的损失,寻找调整方法并减少损失。一旦计算出该导数,将进行最后一步也就是权重更新。所有的过滤器的权重将会更新,以便它们顺着梯度方向改变。


<img src="https://pic4.zhimg.com/50/v2-277722f38cdc66537c2bffbda47a3617_hd.png" data-rawwidth="606" data-rawheight="99" class="origin_image zh-lightbox-thumb" width="606" data-original="https://pic4.zhimg.com/v2-277722f38cdc66537c2bffbda47a3617_r.png">学习速率是一个由程序员决定的参数。高学习速率意味着权重更新的动作更大,因此可能该模式将花费更少的时间收敛到最优权重。然而,学习速率过高会导致跳动过大,不够准确以致于达不到最优点。 学习速率是一个由程序员决定的参数。高学习速率意味着权重更新的动作更大,因此可能该模式将花费更少的时间收敛到最优权重。然而,学习速率过高会导致跳动过大,不够准确以致于达不到最优点。
<img src="https://pic1.zhimg.com/50/v2-112ee3cfba309c85245c3a2fd6d42a04_hd.png" data-rawwidth="640" data-rawheight="198" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic1.zhimg.com/v2-112ee3cfba309c85245c3a2fd6d42a04_r.png">

总的来说,前向传导、损失函数、后向传导、以及参数更新被称为一个学习周期。对每一训练图片,程序将重复固定数目的周期过程。一旦完成了最后训练样本上的参数更新,网络有望得到足够好的训练,以便层级中的权重得到正确调整。


测试


最后,为了检验 CNN 能否工作,我们准备不同的另一组图片与标记集(不能在训练和测试中使用相同的!)并让它们通过这个 CNN。我们将输出与实际情况(ground truth )相比较,看看网络是否有效!


企业如何使用 CNN


数据、数据、数据。数据越多的企业在竞争中越发彰显优势。你提供给网络的训练数据越多,你能进行的训练迭代也越多,紧接着权重更新也多,那么当用于产品时调整出的网络自然就好。Facebook (和 Instagram)可以使用它如今拥有的十几亿用户的图片,Pinterest 可以使用它站点上 500 亿花瓣的信息,谷歌可以使用搜索数据,亚马逊可以使用每天销售的数以百万计的商品数据。而你现在也知道它们使用数据背后的神奇之处了。


Part 2:卷积神经网络中的部分问题



引言


在这篇文章中,我们将更深入地介绍有关卷积神经网络(ConvNet)的详细情况。声明:我确实知道本文中一部分内容相当复杂,可以用一整篇文章进行介绍。但为了在保持全面性的同时保证简洁,我会在文章中相关位置提供一些更详细解释该相关主题的论文链接。


步幅和填充


好了,现在来看一下我们的卷积神经网络。还记得过滤器、感受野和卷积吗?很好。现在,要改变每一层的行为,有两个主要参数是我们可以调整的。选择了过滤器的尺寸以后,我们还需要选择步幅(stride)和填充(padding)。


步幅控制着过滤器围绕输入内容进行卷积计算的方式。在第一部分我们举的例子中,过滤器通过每次移动一个单元的方式对输入内容进行卷积。过滤器移动的距离就是步幅。在那个例子中,步幅被默认设置为1。步幅的设置通常要确保输出内容是一个整数而非分数。让我们看一个例子。想象一个 7 x 7 的输入图像,一个 3 x 3 过滤器(简单起见不考虑第三个维度),步幅为 1。这是一种惯常的情况。

<img src="https://pic4.zhimg.com/50/v2-504ba01c8af8e2d7d41957ddaa4fe6d3_hd.png" data-rawwidth="594" data-rawheight="236" class="origin_image zh-lightbox-thumb" width="594" data-original="https://pic4.zhimg.com/v2-504ba01c8af8e2d7d41957ddaa4fe6d3_r.png">还是老一套,对吧?看你能不能试着猜出如果步幅增加到 2,输出内容会怎么样。还是老一套,对吧?看你能不能试着猜出如果步幅增加到 2,输出内容会怎么样。

<img src="https://pic3.zhimg.com/50/v2-c4a7b49deda73e2b26232d12db7e77c6_hd.png" data-rawwidth="627" data-rawheight="247" class="origin_image zh-lightbox-thumb" width="627" data-original="https://pic3.zhimg.com/v2-c4a7b49deda73e2b26232d12db7e77c6_r.png">

所以,正如你能想到的,感受野移动了两个单元,输出内容同样也会减小。注意,如果试图把我们的步幅设置成 3,那我们就会难以调节间距并确保感受野与输入图像匹配。正常情况下,程序员如果想让接受域重叠得更少并且想要更小的空间维度(spatial dimensions)时,他们会增加步幅。


现在让我们看一下填充(padding)。在此之前,想象一个场景:当你把 5 x 5 x 3 的过滤器用在 32 x 32 x 3 的输入上时,会发生什么?输出的大小会是 28 x 28 x 3。注意,这里空间维度减小了。如果我们继续用卷积层,尺寸减小的速度就会超过我们的期望。在网络的早期层中,我们想要尽可能多地保留原始输入内容的信息,这样我们就能提取出那些低层的特征。比如说我们想要应用同样的卷积层,但又想让输出量维持为 32 x 32 x 3 。为做到这点,我们可以对这个层应用大小为 2 的零填充(zero padding)。零填充在输入内容的边界周围补充零。如果我们用两个零填充,就会得到一个 36 x 36 x 3 的输入卷。

<img src="https://pic3.zhimg.com/50/v2-16ad975f95ef7a45ab836fa563e73736_hd.png" data-rawwidth="640" data-rawheight="248" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-16ad975f95ef7a45ab836fa563e73736_r.png">

如果我们在输入内容的周围应用两次零填充,那么输入量就为 32×32×3。然后,当我们应用带有 3 个 5×5×3 的过滤器,以 1 的步幅进行处理时,我们也可以得到一个 32×32×3 的输出


如果你的步幅为 1,而且把零填充设置为

<img src="https://pic4.zhimg.com/50/v2-151ea0d356f24533867c018bec7c3127_hd.png" data-rawwidth="425" data-rawheight="52" class="origin_image zh-lightbox-thumb" width="425" data-original="https://pic4.zhimg.com/v2-151ea0d356f24533867c018bec7c3127_r.png">

K 是过滤器尺寸,那么输入和输出内容就总能保持一致的空间维度。


计算任意给定卷积层的输出的大小的公式是

<img src="https://pic1.zhimg.com/50/v2-47d83d1bb16072a57d5c1fbb49991d68_hd.png" data-rawwidth="302" data-rawheight="53" class="content_image" width="302">

其中 O 是输出尺寸,K 是过滤器尺寸,P 是填充,S 是步幅。


选择超参数


我们怎么知道要用多少层、多少卷积层、过滤器尺寸是多少、以及步幅和填充值多大呢?这些问题很重要,但又没有一个所有研究人员都在使用的固定标准。这是因为神经网络很大程度上取决于你的数据类型。图像的大小、复杂度、图像处理任务的类型以及其他更多特征的不同都会造成数据的不同。对于你的数据集,想出如何选择超参数的一个方法是找到能创造出图像在合适尺度上抽象的正确组合。


ReLU(修正线性单元)层


在每个卷积层之后,通常会立即应用一个非线性层(或激活层)。其目的是给一个在卷积层中刚经过线性计算操作(只是数组元素依次(element wise)相乘与求和)的系统引入非线性特征。过去,人们用的是像双曲正切和 S 型函数这样的非线性方程,但研究者发现 ReLU 层效果好得多,因为神经网络能够在准确度不发生明显改变的情况下把训练速度提高很多(由于计算效率增加)。它同样能帮助减轻梯度消失的问题——由于梯度以指数方式在层中消失,导致网络较底层的训练速度非常慢。ReLU 层对输入内容的所有值都应用了函数 f(x) = max(0, x)。用基本术语来说,这一层把所有的负激活(negative activation)都变为零。这一层会增加模型乃至整个神经网络的非线性特征,而且不会影响卷积层的感受野。


  • 参见 Geoffrey Hinton(即深度学习之父)的论文:Rectified Linear Units Improve Restricted Boltzmann Machines


池化层


在几个 ReLU 层之后,程序员也许会选择用一个池化层(pooling layer)。它同时也被叫做下采样(downsampling)层。在这个类别中,也有几种可供选择的层,最受欢迎的就是最大池化( max-pooling)。它基本上采用了一个过滤器(通常是 2x2 的)和一个同样长度的步幅。然后把它应用到输入内容上,输出过滤器卷积计算的每个子区域中的最大数字。

<img src="https://pic2.zhimg.com/50/v2-a944f0f847266c28ad93f2b6b9986e65_hd.png" data-rawwidth="640" data-rawheight="333" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-a944f0f847266c28ad93f2b6b9986e65_r.png">

带有 2×2 和过滤器的且步幅为 2 的最大池化的例子


池化层还有其他选择,比如平均池化(average pooling)和 L2-norm 池化 。这一层背后的直观推理是:一旦我们知道了原始输入(这里会有一个高激活值)中一个特定的特征,它与其它特征的相对位置就比它的绝对位置更重要。可想而知,这一层大幅减小了输入卷的空间维度(长度和宽度改变了,但深度没变)。这到达了两个主要目的。第一个是权重参数的数目减少到了75%,因此降低了计算成本。第二是它可以控制过拟合(overfitting)。这个术语是指一个模型与训练样本太过匹配了,以至于用于验证和检测组时无法产生出好的结果。出现过拟合的表现是一个模型在训练集能达到 100% 或 99% 的准确度,而在测试数据上却只有50%。


Dropout 层


如今,Dropout 层在神经网络有了非常明确的功能。上一节,我们讨论了经过训练后的过拟合问题:训练之后,神经网络的权重与训练样本太过匹配以至于在处理新样本的时候表现平平。Dropout 的概念在本质上非常简单。Dropout 层将「丢弃(drop out)」该层中一个随机的激活参数集,即在前向通过(forward pass)中将这些激活参数集设置为 0。简单如斯。既然如此,这些简单而且似乎不必要且有些反常的过程的好处是什么?在某种程度上,这种机制强制网络变得更加冗余。这里的意思是:该网络将能够为特定的样本提供合适的分类或输出,即使一些激活参数被丢弃。此机制将保证神经网络不会对训练样本「过于匹配」,这将帮助缓解过拟合问题。另外,Dropout 层只能在训练中使用,而不能用于测试过程,这是很重要的一点。


  • 参考 Geoffrey Hinton 的论文:Dropout: A Simple Way to Prevent Neural Networks from Overfitting


网络层中的网络


网络层中的网络指的是一个使用了 1 x 1 尺寸的过滤器的卷积层。现在,匆匆一瞥,你或许会好奇为何这种感受野大于它们所映射空间的网络层竟然会有帮助。然而,我们必须谨记 1x1 的卷积层跨越了特定深度,所以我们可以设想一个1 x 1 x N 的卷积层,此处 N 代表该层应用的过滤器数量。该层有效地使用 N 维数组元素依次相乘的乘法,此时 N 代表的是该层的输入的深度。


  • 参阅 Min Lin 的论文:Network In Network


分类、定位、检测、分割


本系列第一部分使用的案例中,我们观察了图像分类任务。这个过程是:获取输入图片,输出一套分类的类数(class number)。然而当我们执行类似目标定位的任务时,我们要做的不只是生成一个类标签,而是生成一个描述图片中物体suo所在位置的边界框。

<img src="https://i-blog.csdnimg.cn/blog_migrate/0e95b7d746d086804dda9639dc7e1a53.jpeg" data-rawwidth="640" data-rawheight="257" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-53c1e0def4fdc2119fd13f2656234ef7_r.jpg">

我们也有目标检测的任务,这需要图片上所有目标的定位任务都已完成。


因此,你将获得多个边界框和多个类标签。


最终,我们将执行目标分割的任务:我们需要输出类标签的同时输出图片中每个目标的轮廓。


<img src="https://i-blog.csdnimg.cn/blog_migrate/6b8497aab06370138492e99292c62f75.jpeg" data-rawwidth="640" data-rawheight="250" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-24822a554ee977795e0d0ab22eaa0ff2_r.jpg">

关于目标检测、定位、分割的论文有很多,这里就不一一列出了。


迁移学习


如今,深度学习领域一个常见的误解在于没有谷歌那样的巨量数据,你将没有希望创建一个有效的深度学习模型。尽管数据是创建网络中至关重要的部分,迁移学习的思路将帮助我们降低数据需求。迁移学习指的是利用预训练模型(神经网络的权重和参数都已经被其他人利用更大规模的数据集训练好了)并用自己的数据集将模型「微调」的过程。这种思路中预训练模型扮演着特征提取器的角色。你将移除网络的最后一层并用你自有的分类器置换(取决于你的问题空间)。然后冻结其他所有层的权重并正常训练该网络(冻结这些层意味着在梯度下降/最优化过程中保持权值不变)。


让我们探讨一下为什么做这项工作。比如说我们正在讨论的这个预训练模型是在 ImageNet (一个包含一千多个分类,一千四百万张图像的数据集)上训练的 。当我们思考神经网络的较低层时,我们知道它们将检测类似曲线和边缘这样的特征。现在,除非你有一个极为独特的问题空间和数据集,你的神经网络也会检测曲线和边缘这些特征。相比通过随机初始化权重训练整个网络,我们可以利用预训练模型的权重(并冻结)聚焦于更重要的层(更高层)进行训练。如果你的数据集不同于 ImageNet 这样的数据集,你必须训练更多的层级而只冻结一些低层的网络。


  • Yoshua Bengio (另外一个深度学习先驱 )论文:How transferable are features in deep neural networks?

  • Ali Sharif Razavian 论文:CNN Features off-the-shelf: an Astounding Baseline for Recognition

  • Jeff Donahue 论文:DeCAF: A Deep Convolutional Activation Feature for Generic Visual Recognition


数据增强技术


现在我们对卷积网络中数据的重要性可能已经感到有些麻木了,所以我们来谈下如何利用一些简单的转换方法将你现有的数据集变得更大。正如我们之前所提及的,当计算机将图片当作输入时,它将用一个包含一列像素值的数组描述(这幅图)。若是图片左移一个像素。对你和我来说,这种变化是微不可察的。然而对计算机而已,这种变化非常显著:这幅图的类别和标签保持不变,数组却变化了。这种改变训练数据的数组表征而保持标签不变的方法被称作数据增强技术。这是一种人工扩展数据集的方法。人们经常使用的增强方法包括灰度变化、水平翻转、垂直翻转、随机编组、色值跳变、翻译、旋转等其他多种方法。通过利用这些训练数据的转换方法,你将获得两倍甚至三倍于原数据的训练样本。


深度 | 从入门到精通:卷积神经网络初学者指南(附论文)

该文是卷积神经网络--介绍,并假设你理解前馈神经网络。

如果不是,强烈建议你读完如何简单形象又有趣地讲解神经网络是什么? 后再来读该篇。

目录

  • 视觉感知
    • 画面识别是什么
    • 识别结果取决于什么
  • 图像表达
    • 画面识别的输入
    • 画面不变形
  • 前馈神经网络做画面识别的不足
  • 卷积神经网络做画面识别
    • 局部连接
    • 空间共享
    • 输出空间表达
    • Depth维的处理
    • Zero padding
    • 形状、概念抓取
    • 多filters
    • 非线性
    • 输出尺寸控制
    • 矩阵乘法执行卷积
    • Max pooling
    • 全连接层
    • 结构发展
  • 画面不变性的满足
    • 平移不变性
    • 旋转和视角不变性
    • 尺寸不变性
    • Inception的理解
    • 1x1卷积核理解
    • 跳层连接ResNet

视觉感知

一、画面识别是什么任务?

学习知识的第一步就是明确任务,清楚该知识的输入输出。卷积神经网络最初是服务于画面识别的,所以我们先来看看画面识别的实质是什么。

先观看几组动物与人类视觉的差异对比图。

1. 苍蝇的视觉和人的视觉的差异

<img src="https://i-blog.csdnimg.cn/blog_migrate/2152191d5bd327c98e722f453ae2d643.jpeg" data-caption="" data-rawwidth="384" data-rawheight="216" class="content_image" width="384"> <img src="https://pic2.zhimg.com/50/v2-4a0ea7ba42166b62bc4f42e8b150815d_hd.png" data-caption="" data-rawwidth="1280" data-rawheight="479" class="origin_image zh-lightbox-thumb" width="1280" data-original="https://pic2.zhimg.com/v2-4a0ea7ba42166b62bc4f42e8b150815d_r.png">


2. 蛇的视觉和人的视觉的差异

<img src="https://i-blog.csdnimg.cn/blog_migrate/b19180680fd0cc36773007e3aa1466bd.jpeg" data-caption="" data-rawwidth="384" data-rawheight="216" class="content_image" width="384"> <img src="https://pic4.zhimg.com/50/v2-3da84b5b80ba7a0d779284566f80be93_hd.png" data-caption="" data-rawwidth="1280" data-rawheight="479" class="origin_image zh-lightbox-thumb" width="1280" data-original="https://pic4.zhimg.com/v2-3da84b5b80ba7a0d779284566f80be93_r.png">


(更多对比图请参考链接

通过上面的两组对比图可以知道,即便是相同的图片经过不同的视觉系统,也会得到不同的感知。

这里引出一条知识:生物所看到的景象并非世界的原貌,而是长期进化出来的适合自己生存环境的一种感知方式。 蛇的猎物一般是夜间行动,所以它就进化出了一种可以在夜间也能很好观察的感知系统,感热。

任何视觉系统都是将图像反光与脑中所看到的概念进行关联。

<img src="https://pic4.zhimg.com/50/v2-2c82abd20c4e7c40f7f13f035b924b0b_hd.png" data-caption="" data-rawwidth="223" data-rawheight="97" class="content_image" width="223">


所以画面识别实际上并非识别这个东西客观上是什么,而是寻找人类的视觉关联方式,并再次应用。 如果我们不是人类,而是蛇类,那么画面识别所寻找的 就和现在的不一样。

画面识别实际上是寻找(学习)人类的视觉关联方式 ,并再次应用

二、图片被识别成什么取决于哪些因素?

下面用两张图片来体会识别结果取决于哪些因素。

1. 老妇与少女

<img src="https://i-blog.csdnimg.cn/blog_migrate/b6e3154b3bad36659665a19cf93eb646.jpeg" data-caption="" data-rawwidth="198" data-rawheight="255" class="content_image" width="198">


请观察上面这张图片,你看到的是老妇还是少女? 以不同的方式去观察这张图片会得出不同的答案。 图片可以观察成有大鼻子、大眼睛的老妇。也可以被观察成少女,但这时老妇的嘴会被识别成少女脖子上的项链,而老妇的眼睛则被识别为少女的耳朵。

2. 海豚与男女

<img src="https://i-blog.csdnimg.cn/blog_migrate/c80bc1fc015523c744a952153d66e35e.jpeg" data-caption="" data-rawwidth="394" data-rawheight="509" class="content_image" width="394">


上面这张图片如果是成人观察,多半看到的会是一对亲热的男女。倘若儿童看到这张图片,看到的则会是一群海豚(男女的轮廓是由海豚构造出的)。所以,识别结果受年龄,文化等因素的影响,换句话说:

图片被识别成什么不仅仅取决于图片本身,还取决于图片是如何被观察的。

图像表达

我们知道了“画面识别是从大量的(x,y)数据中寻找人类的视觉关联方式 ,并再次应用。 其x-是输入,表示所看到的东西y-输出,表示该东西是什么。

在自然界中,x是物体的反光,那么在计算机中,图像又是如何被表达和存储的呢?

<img src="https://pic2.zhimg.com/50/v2-d2859e5c486ed704492ab80079e99535_hd.gif" data-caption="" data-rawwidth="291" data-rawheight="290" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/7602331a767af1638c458a98510d824c.jpeg" class="content_image" width="291">


[from]

图像在计算机中是一堆按顺序排列的数字,数值为0到255。0表示最暗,255表示最亮。 你可以把这堆数字用一个长长的向量来表示,也就是tensorflow的mnist教程中784维向量的表示方式。 然而这样会失去平面结构的信息,为保留该结构信息,通常选择矩阵的表示方式:28x28的矩阵。

上图是只有黑白颜色的灰度图,而更普遍的图片表达方式是RGB颜色模型,即红(Red)、绿(Green)、蓝(Blue)三原色的色光以不同的比例相加,以产生多种多样的色光。

这样,RGB颜色模型中,单个矩阵就扩展成了有序排列的三个矩阵,也可以用三维张量去理解,其中的每一个矩阵又叫这个图片的一个channel。

在电脑中,一张图片是数字构成的“长方体”。可用 宽width, 高height, 深depth 来描述,如图。

<img src="https://pic1.zhimg.com/50/v2-0d24890b2e0d73f4ce4ad17ebfb2d0c4_hd.png" data-caption="" data-rawwidth="305" data-rawheight="252" class="content_image" width="305">


画面识别的输入 x是shape为(width, height, depth)的三维张量。

接下来要考虑的就是该如何处理这样的“数字长方体”。

画面不变性

在决定如何处理“数字长方体”之前,需要清楚所建立的网络拥有什么样的特点。 我们知道一个物体不管在画面左侧还是右侧,都会被识别为同一物体,这一特点就是不变性(invariance),如下图所示。

<img src="https://pic3.zhimg.com/50/v2-b9aed3dd68b9818561faa7d8ed24ea5a_hd.png" data-caption="" data-rawwidth="567" data-rawheight="769" class="origin_image zh-lightbox-thumb" width="567" data-original="https://pic3.zhimg.com/v2-b9aed3dd68b9818561faa7d8ed24ea5a_r.png">


我们希望所建立的网络可以尽可能的满足这些不变性特点。

为了理解卷积神经网络对这些不变性特点的贡献,我们将用不具备这些不变性特点的前馈神经网络来进行比较。

图片识别--前馈神经网络

方便起见,我们用depth只有1的灰度图来举例。 想要完成的任务是:在宽长为4x4的图片中识别是否有下图所示的“横折”。 图中,黄色圆点表示值为0的像素,深色圆点表示值为1的像素。 我们知道不管这个横折在图片中的什么位置,都会被认为是相同的横折。

<img src="https://pic2.zhimg.com/50/v2-18c11c6f485e9f1bbc9a50eb3d248439_hd.png" data-caption="" data-rawwidth="411" data-rawheight="374" class="content_image" width="411">


若训练前馈神经网络来完成该任务,那么表达图像的三维张量将会被摊平成一个向量,作为网络的输入,即(width, height, depth)为(4, 4, 1)的图片会被展成维度为16的向量作为网络的输入层。再经过几层不同节点个数的隐藏层,最终输出两个节点,分别表示“有横折的概率”和“没有横折的概率”,如下图所示。

<img src="https://pic2.zhimg.com/50/v2-2b411af47b1cad7b727bb676c847ce59_hd.png" data-caption="" data-rawwidth="499" data-rawheight="505" class="origin_image zh-lightbox-thumb" width="499" data-original="https://pic2.zhimg.com/v2-2b411af47b1cad7b727bb676c847ce59_r.png">


下面我们用数字(16进制)对图片中的每一个像素点(pixel)进行编号。 当使用右侧那种物体位于中间的训练数据来训练网络时,网络就只会对编号为5,6,9,a的节点的权重进行调节。 若让该网络识别位于右下角的“横折”时,则无法识别。

<img src="https://pic2.zhimg.com/50/v2-ce9919e4930c1f29241afec0538b2605_hd.png" data-caption="" data-rawwidth="816" data-rawheight="505" class="origin_image zh-lightbox-thumb" width="816" data-original="https://pic2.zhimg.com/v2-ce9919e4930c1f29241afec0538b2605_r.png">


解决办法是用大量物体位于不同位置的数据训练,同时增加网络的隐藏层个数从而扩大网络学习这些变体的能力。

然而这样做十分不效率,因为我们知道在左侧的“横折”也好,还是在右侧的“横折”也罢,大家都是“横折”。 为什么相同的东西在位置变了之后要重新学习?有没有什么方法可以将中间所学到的规律也运用在其他的位置? 换句话说,也就是让不同位置用相同的权重

图片识别--卷积神经网络

卷积神经网络就是让权重在不同位置共享的神经网络。

局部连接

在卷积神经网络中,我们先选择一个局部区域,用这个局部区域去扫描整张图片。 局部区域所圈起来的所有节点会被连接到下一层的一个节点上。

为了更好的和前馈神经网络做比较,我将这些以矩阵排列的节点展成了向量。 下图展示了被红色方框所圈中编号为0,1,4,5的节点是如何通过w_1,w_2,w_3,w_4连接到下一层的节点0上的。

<img src="https://pic1.zhimg.com/50/v2-e877b9099b1139c1a34b0bf66bf92aa4_hd.png" data-caption="" data-rawwidth="513" data-rawheight="514" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic1.zhimg.com/v2-e877b9099b1139c1a34b0bf66bf92aa4_r.png">


这个带有连接强弱的红色方框就叫做 filterkernelfeature detector。 而filter的范围叫做filter size,这里所展示的是2x2的filter size。

\left[ \begin{matrix} w_1&w_2\\ w_3&w_4\\ \end{matrix} \right] (1)

第二层的节点0的数值就是局部区域的线性组合,即被圈中节点的数值乘以对应的权重后相加。 用x表示输入值,y表示输出值,用图中标注数字表示角标,则下面列出了两种计算编号为0的输出值y_0的表达式。

注:在局部区域的线性组合后,也会和前馈神经网络一样,加上一个偏移量b_0

\begin{split} y_0 &= x_0*w_1 + x_1*w_2+ x_4*w_3+ x_5*w_4+b_0\\y_0 &= \left[ \begin{matrix} w_1&w_2& w_3&w_4 \end{matrix} \right] \cdot \left[ \begin{matrix} x_0\\ x_1\\ x_4\\ x_5\\ \end{matrix} \right]+b_0 \end{split} (2)

空间共享

当filter扫到其他位置计算输出节点y_i 时,w_1,w_2,w_3,w_4包括b_0是共用的。

下面这张动态图展示了当filter扫过不同区域时,节点的链接方式。 动态图的最后一帧则显示了所有连接。 可以注意到,每个输出节点并非像前馈神经网络中那样与全部的输入节点连接,而是部分连接。 这也就是为什么大家也叫前馈神经网络(feedforward neural network)为fully-connected neural network。 图中显示的是一步一步的移动filter来扫描全图,一次移动多少叫做stride。

<img src="https://pic1.zhimg.com/50/v2-4fd0400ccebc8adb2dffe24aac163e70_hd.gif" data-caption="" data-rawwidth="513" data-rawheight="514" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/84d912ca7f1819f0ce18f49a79655681.jpeg" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic1.zhimg.com/v2-4fd0400ccebc8adb2dffe24aac163e70_r.gif">


空间共享也就是卷积神经网络所引入的先验知识。

输出表达

如先前在图像表达中提到的,图片不用向量去表示是为了保留图片平面结构的信息。 同样的,卷积后的输出若用上图的排列方式则丢失了平面结构信息。 所以我们依然用矩阵的方式排列它们,就得到了下图所展示的连接。

<img src="https://pic2.zhimg.com/50/v2-e1691956fd1beb5d7a637924a1a73d91_hd.png" data-caption="" data-rawwidth="513" data-rawheight="514" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic2.zhimg.com/v2-e1691956fd1beb5d7a637924a1a73d91_r.png">


这也就是你们在网上所看到的下面这张图。在看这张图的时候请结合上图的连接一起理解,即输入(绿色)的每九个节点连接到输出(粉红色)的一个节点上的。

<img src="https://pic3.zhimg.com/50/v2-7fce29335f9b43bce1b373daa40cccba_hd.gif" data-caption="" data-rawwidth="526" data-rawheight="384" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/c648e567095fc1e076937488d17201bc.jpeg" class="origin_image zh-lightbox-thumb" width="526" data-original="https://pic3.zhimg.com/v2-7fce29335f9b43bce1b373daa40cccba_r.gif">


经过一个feature detector计算后得到的粉红色区域也叫做一个“Convolved Feature” 或 “Activation Map” 或 “Feature Map”。

Depth维的处理

现在我们已经知道了depth维度只有1的灰度图是如何处理的。 但前文提过,图片的普遍表达方式是下图这样有3个channels的RGB颜色模型。 当depth为复数的时候,每个feature detector是如何卷积的?

<img src="https://pic1.zhimg.com/50/v2-0d24890b2e0d73f4ce4ad17ebfb2d0c4_hd.png" data-caption="" data-rawwidth="305" data-rawheight="252" class="content_image" width="305">


现象:2x2所表达的filter size中,一个2表示width维上的局部连接数,另一个2表示height维上的局部连接数,并却没有depth维上的局部连接数,是因为depth维上并非局部,而是全部连接的。

在2D卷积中,filter在张量的width维, height维上是局部连接,在depth维上是贯串全部channels的。

类比:想象在切蛋糕的时候,不管这个蛋糕有多少层,通常大家都会一刀切到底,但是在长和宽这两个维上是局部切割。

下面这张图展示了,在depth为复数时,filter是如何连接输入节点到输出节点的。 图中红、绿、蓝颜色的节点表示3个channels。 黄色节点表示一个feature detector卷积后得到的Feature Map。 其中被透明黑框圈中的12个节点会被连接到黄黑色的节点上。

  • 在输入depth为1时:被filter size为2x2所圈中的4个输入节点连接到1个输出节点上。
  • 在输入depth为3时:被filter size为2x2,但是贯串3个channels后,所圈中的12个输入节点连接到1个输出节点上。
  • 在输入depth为n时:2x2xn个输入节点连接到1个输出节点上。
<img src="https://pic3.zhimg.com/50/v2-23db15ec3f783bbb5cf811711e46dbba_hd.png" data-caption="" data-rawwidth="302" data-rawheight="382" class="content_image" width="302">


(可从vectary在3D编辑下查看)

注意:三个channels的权重并不共享。 即当深度变为3后,权重也跟着扩增到了三组,如式子(3)所示,不同channels用的是自己的权重。 式子中增加的角标r,g,b分别表示red channel, green channel, blue channel的权重。

\left[ \begin{matrix} w_{r1}&w_{r2}\\ w_{r3}&w_{r4}\\ \end{matrix} \right], \left[ \begin{matrix} w_{g1}&w_{g2}\\ w_{g3}&w_{g4}\\ \end{matrix} \right], \left[ \begin{matrix} w_{b1}&w_{b2}\\ w_{b3}&w_{b4}\\ \end{matrix} \right] (3)

计算例子:用x_{r0}表示red channel的编号为0的输入节点,x_{g5}表示green channel编号为5个输入节点。x_{b1}表示blue channel。如式子(4)所表达,这时的一个输出节点实际上是12个输入节点的线性组合。

\begin{split} y_0 &= x_{r0}*w_{r1} + x_{r1}*w_{r2}+ x_{r4}*w_{r3}+ x_{r5}*w_{r4}+ x_{g0}*w_{g1} + x_{g1}*w_{g2}+ x_{g4}*w_{g3}+ x_{g5}*w_{g4}+ x_{b0}*w_{b1} + x_{b1}*w_{b2}+ x_{b4}*w_{b3}+ x_{b5}*w_{b4}+b_0\\y_0 &= \left[ \begin{matrix} w_{r1}&w_{r2}& w_{r3}&w_{r4} \end{matrix} \right] \cdot \left[ \begin{matrix} x_{r0}\\ x_{r1}\\ x_{r4}\\ x_{r5}\\ \end{matrix} \right] +\left[ \begin{matrix} w_{g1}&w_{g2}& w_{g3}&w_{g4} \end{matrix} \right] \cdot \left[ \begin{matrix} x_{g0}\\ x_{g1}\\ x_{g4}\\ x_{g5}\\ \end{matrix} \right]+\left[ \begin{matrix} w_{b1}&w_{b2}& w_{b3}&w_{b4} \end{matrix} \right] \cdot \left[ \begin{matrix} x_{b0}\\ x_{b1}\\ x_{b4}\\ x_{b5}\\ \end{matrix} \right]+b_0\end{split}(4)

当filter扫到其他位置计算输出节点y_i时,那12个权重在不同位置是共用的,如下面的动态图所展示。 透明黑框圈中的12个节点会连接到被白色边框选中的黄色节点上。

<img src="https://pic3.zhimg.com/50/v2-0bc83b72ef50099b70a10cc3ab528f62_hd.gif" data-caption="" data-rawwidth="326" data-rawheight="455" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/0bb18dfa8fe95c252604e622f1461d37.jpeg" class="content_image" width="326">


每个filter会在width维, height维上,以局部连接和空间共享,并贯串整个depth维的方式得到一个Feature Map。

Zero padding

细心的读者应该早就注意到了,4x4的图片被2x2的filter卷积后变成了3x3的图片,每次卷积后都会小一圈的话,经过若干层后岂不是变的越来越小? Zero padding就可以在这时帮助控制Feature Map的输出尺寸,同时避免了边缘信息被一步步舍弃的问题。

例如:下面4x4的图片在边缘Zero padding一圈后,再用3x3的filter卷积后,得到的Feature Map尺寸依然是4x4不变。

<img src="https://pic2.zhimg.com/50/v2-c1010eb5dcf032ea95eab495a45f9b31_hd.png" data-caption="" data-rawwidth="173" data-rawheight="173" class="content_image" width="173">


通常大家都想要在卷积时保持图片的原始尺寸。 选择3x3的filter和1的zero padding,或5x5的filter和2的zero padding可以保持图片的原始尺寸。 这也是为什么大家多选择3x3和5x5的filter的原因。 另一个原因是3x3的filter考虑到了像素与其距离为1以内的所有其他像素的关系,而5x5则是考虑像素与其距离为2以内的所有其他像素的关系。

尺寸:Feature Map的尺寸等于(input_size + 2 * padding_size − filter_size)/stride+1。

注意:上面的式子是计算width或height一维的。padding_size也表示的是单边补零的个数。例如(4+2-3)/1+1 = 4,保持原尺寸。

不用去背这个式子。其中(input_size + 2 * padding_size)是经过Zero padding扩充后真正要卷积的尺寸。 减去 filter_size后表示可以滑动的范围。 再除以可以一次滑动(stride)多少后得到滑动了多少次,也就意味着得到了多少个输出节点。 再加上第一个不需要滑动也存在的输出节点后就是最后的尺寸。

形状、概念抓取

知道了每个filter在做什么之后,我们再来思考这样的一个filter会抓取到什么样的信息。

我们知道不同的形状都可由细小的“零件”组合而成的。比如下图中,用2x2的范围所形成的16种形状可以组合成格式各样的“更大”形状。

卷积的每个filter可以探测特定的形状。又由于Feature Map保持了抓取后的空间结构。若将探测到细小图形的Feature Map作为新的输入再次卷积后,则可以由此探测到“更大”的形状概念。 比如下图的第一个“大”形状可由2,3,4,5基础形状拼成。第二个可由2,4,5,6组成。第三个可由6,1组成。

<img src="https://pic1.zhimg.com/50/v2-f53f6ac43abd2555cfbbba6ea7fdc0e4_hd.png" data-caption="" data-rawwidth="484" data-rawheight="291" class="origin_image zh-lightbox-thumb" width="484" data-original="https://pic1.zhimg.com/v2-f53f6ac43abd2555cfbbba6ea7fdc0e4_r.png">


除了基础形状之外,颜色、对比度等概念对画面的识别结果也有影响。卷积层也会根据需要去探测特定的概念。

可以从下面这张图中感受到不同数值的filters所卷积过后的Feature Map可以探测边缘,棱角,模糊,突出等概念。

<img src="https://pic1.zhimg.com/50/v2-644d108587a6ce7fa471ede5d2e11e98_hd.png" data-caption="" data-rawwidth="342" data-rawheight="562" class="content_image" width="342">


[from]

如我们先前所提,图片被识别成什么不仅仅取决于图片本身,还取决于图片是如何被观察的。

而filter内的权重矩阵W是网络根据数据学习得到的,也就是说,我们让神经网络自己学习以什么样的方式去观察图片。

拿老妇与少女的那幅图片举例,当标签是少女时,卷积网络就会学习抓取可以成少女的形状、概念。 当标签是老妇时,卷积网络就会学习抓取可以成老妇的形状、概念。

下图展现了在人脸识别中经过层层的卷积后,所能够探测的形状、概念也变得越来越抽象和复杂。

<img src="https://i-blog.csdnimg.cn/blog_migrate/3ab2c504ba69e38c6e26885c5158a59a.jpeg" data-caption="" data-rawwidth="366" data-rawheight="546" class="content_image" width="366">


卷积神经网络会尽可能寻找最能解释训练数据的抓取方式。

多filters

每个filter可以抓取探测特定的形状的存在。 假如我们要探测下图的长方框形状时,可以用4个filters去探测4个基础“零件”。

<img src="https://pic1.zhimg.com/50/v2-6df64fccc9a8e2f696626f85233acb3c_hd.png" data-caption="" data-rawwidth="123" data-rawheight="127" class="content_image" width="123">


<img src="https://pic4.zhimg.com/50/v2-65461a21a909eca2e190c54db59a2c8f_hd.png" data-caption="" data-rawwidth="315" data-rawheight="82" class="content_image" width="315">


因此我们自然而然的会选择用多个不同的filters对同一个图片进行多次抓取。 如下图(动态图过大,如果显示不出,请看到该链接观看),同一个图片,经过两个(红色、绿色)不同的filters扫描过后可得到不同特点的Feature Maps。 每增加一个filter,就意味着你想让网络多抓取一个特征。

<img src="https://pic2.zhimg.com/50/v2-c7f1ea1d42820b4de30bd548c3986ecd_hd.gif" data-caption="" data-rawwidth="212" data-rawheight="120" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/f0555cb14498d2418222f074797f420d.jpeg" class="content_image" width="212">


[from]

这样卷积层的输出也不再是depth为1的一个平面,而是和输入一样是depth为复数的长方体。

如下图所示,当我们增加一个filter(紫色表示)后,就又可以得到一个Feature Map。 将不同filters所卷积得到的Feature Maps按顺序堆叠后,就得到了一个卷积层的最终输出。

<img src="https://pic1.zhimg.com/50/v2-d11e1d2f2c41b6df713573f8155bc324_hd.png" data-caption="" data-rawwidth="1271" data-rawheight="629" class="origin_image zh-lightbox-thumb" width="1271" data-original="https://pic1.zhimg.com/v2-d11e1d2f2c41b6df713573f8155bc324_r.png">


卷积层的输入是长方体,输出也是长方体。

这样卷积后输出的长方体可以作为新的输入送入另一个卷积层中处理。

加入非线性

和前馈神经网络一样,经过线性组合和偏移后,会加入非线性增强模型的拟合能力。

将卷积所得的Feature Map经过ReLU变换(elementwise)后所得到的output就如下图所展示。

<img src="https://pic3.zhimg.com/50/v2-54a469b2873542e75abf2bc5d8fcaa1a_hd.png" data-caption="" data-rawwidth="748" data-rawheight="280" class="origin_image zh-lightbox-thumb" width="748" data-original="https://pic3.zhimg.com/v2-54a469b2873542e75abf2bc5d8fcaa1a_r.png">


[from]

输出长方体

现在我们知道了一个卷积层的输出也是一个长方体。 那么这个输出长方体的(width, height, depth)由哪些因素决定和控制。

这里直接用CS231n的Summary:

<img src="https://pic1.zhimg.com/50/v2-a9983c3cee935b68c73965bc1abe268c_hd.png" data-caption="" data-rawwidth="383" data-rawheight="376" class="content_image" width="383">


计算例子:请体会CS231n的Convolution Demo部分的演示。

矩阵乘法执行卷积

如果按常规以扫描的方式一步步计算局部节点和filter的权重的点乘,则不能高效的利用GPU的并行能力。 所以更普遍的方法是用两个大矩阵的乘法来一次性囊括所有计算。

因为卷积层的每个输出节点都是由若干个输入节点的线性组合所计算。 因为输出的节点个数是W_2 \times H_2\times D_2,所以就有W_2 \times H_2\times D_2个线性组合。

读过我写的线性代数教程的读者请回忆,矩阵乘矩阵的意义可以理解为批量的线性组合按顺序排列。 其中一个矩阵所表示的信息是多组权重,另一个矩阵所表示的信息是需要进行组合的向量。 大家习惯性的把组成成分放在矩阵乘法的右边,而把权重放在矩阵乘法的左边。 所以这个大型矩阵乘法可以用W_{row}\cdot X_{col}表示,其中W_{row}X_{col}都是矩阵。

<img src="https://pic1.zhimg.com/50/v2-11a4d56793af815eb2b4585d64aec178_hd.png" data-caption="" data-rawwidth="551" data-rawheight="136" class="origin_image zh-lightbox-thumb" width="551" data-original="https://pic1.zhimg.com/v2-11a4d56793af815eb2b4585d64aec178_r.png">


卷积的每个输出是由局部的输入节点和对应的filter权重展成向量后所计算的,如式子(2)。 那么W_{row}中的每一行则是每个filter的权重,有F\cdot F \cdot D_1个; 而X_{col}的每一列是所有需要进行组合的节点(上面的动态图中被黑色透明框圈中的节点),也有F\cdot F \cdot D_1个。X_{col}的列的个数则表示每个filter要滑动多少次才可以把整个图片扫描完,有W_2\cdot H_2次。 因为我们有多个filters,W_{row}的行的个数则是filter的个数K

最后我们得到:

W_{row} \in R^{K \times F\cdot F \cdot D_1}

X_{col} \in R^{F\cdot F \cdot D_1 \times W_2\cdot H_2}

W_{row}\cdot X_{col} \in R^{K \times W_2\cdot H_2}

当然矩阵乘法后需要将W_{row}\cdot X_{col}整理成形状为W_2 \times H_2\times D_2的三维张量以供后续处理(如再送入另一个卷积层)。X_{col}则也需要逐步的局部滑动图片,最后堆叠构成用于计算矩阵乘法的形式。

Max pooling

在卷积后还会有一个pooling的操作,尽管有其他的比如average pooling等,这里只提max pooling。

max pooling的操作如下图所示:整个图片被不重叠的分割成若干个同样大小的小块(pooling size)。每个小块内只取最大的数字,再舍弃其他节点后,保持原有的平面结构得出output。

<img src="https://i-blog.csdnimg.cn/blog_migrate/04a2dc413ef193903baf7c9c5071d312.jpeg" data-caption="" data-rawwidth="787" data-rawheight="368" class="origin_image zh-lightbox-thumb" width="787" data-original="https://pic1.zhimg.com/v2-1a4b2a3795d8f073e921d766e70ce6ec_r.jpg">


[from]

max pooling在不同的depth上是分开执行的,且不需要参数控制。 那么问题就max pooling有什么作用?部分信息被舍弃后难道没有影响吗?

<img src="https://i-blog.csdnimg.cn/blog_migrate/077b5feae096af9bf3ca526ea5541380.jpeg" data-caption="" data-rawwidth="514" data-rawheight="406" class="origin_image zh-lightbox-thumb" width="514" data-original="https://pic4.zhimg.com/v2-cd717414dcf32dac4df73c00f1e7c6c3_r.jpg">


[from]

Max pooling的主要功能是downsampling,却不会损坏识别结果。 这意味着卷积后的Feature Map中有对于识别物体不必要的冗余信息。 那么我们就反过来思考,这些“冗余”信息是如何产生的。

直觉上,我们为了探测到某个特定形状的存在,用一个filter对整个图片进行逐步扫描。但只有出现了该特定形状的区域所卷积获得的输出才是真正有用的,用该filter卷积其他区域得出的数值就可能对该形状是否存在的判定影响较小。 比如下图中,我们还是考虑探测“横折”这个形状。 卷积后得到3x3的Feature Map中,真正有用的就是数字为3的那个节点,其余数值对于这个任务而言都是无关的。 所以用3x3的Max pooling后,并没有对“横折”的探测产生影响。 试想在这里例子中如果不使用Max pooling,而让网络自己去学习。 网络也会去学习与Max pooling近似效果的权重。因为是近似效果,增加了更多的parameters的代价,却还不如直接进行Max pooling。

<img src="https://pic1.zhimg.com/50/v2-8e9d7ec0662e903e475bd93a64067554_hd.png" data-caption="" data-rawwidth="545" data-rawheight="345" class="origin_image zh-lightbox-thumb" width="545" data-original="https://pic1.zhimg.com/v2-8e9d7ec0662e903e475bd93a64067554_r.png">


Max pooling还有类似“选择句”的功能。假如有两个节点,其中第一个节点会在某些输入情况下最大,那么网络就只在这个节点上流通信息;而另一些输入又会让第二个节点的值最大,那么网络就转而走这个节点的分支。

但是Max pooling也有不好的地方。因为并非所有的抓取都像上图的极端例子。有些周边信息对某个概念是否存在的判定也有影响。 并且Max pooling是对所有的Feature Maps进行等价的操作。就好比用相同网孔的渔网打鱼,一定会有漏网之鱼。

全连接层

当抓取到足以用来识别图片的特征后,接下来的就是如何进行分类。 全连接层(也叫前馈层)就可以用来将最后的输出映射到线性可分的空间。 通常卷积网络的最后会将末端得到的长方体平摊(flatten)成一个长长的向量,并送入全连接层配合输出层进行分类。

卷积神经网络大致就是covolutional layer, pooling layer, ReLu layer, fully-connected layer的组合,例如下图所示的结构。

<img src="https://pic4.zhimg.com/50/v2-cf87890eb8f2358f23a1ac78eb764257_hd.png" data-caption="" data-rawwidth="748" data-rawheight="263" class="origin_image zh-lightbox-thumb" width="748" data-original="https://pic4.zhimg.com/v2-cf87890eb8f2358f23a1ac78eb764257_r.png">


[from]

这里也体现了深层神经网络或deep learning之所以称deep的一个原因:模型将特征抓取层和分类层合在了一起。 负责特征抓取的卷积层主要是用来学习“如何观察”。

下图简述了机器学习的发展,从最初的人工定义特征再放入分类器的方法,到让机器自己学习特征,再到如今尽量减少人为干涉的deep learning。

<img src="https://pic1.zhimg.com/50/v2-60e7c1e89c5aed5b828cbb24fc1e5a80_hd.png" data-caption="" data-rawwidth="566" data-rawheight="789" class="origin_image zh-lightbox-thumb" width="566" data-original="https://pic1.zhimg.com/v2-60e7c1e89c5aed5b828cbb24fc1e5a80_r.png">


[from]

结构发展

以上介绍了卷积神经网络的基本概念。 以下是几个比较有名的卷积神经网络结构,详细的请看CS231n

  • LeNet:第一个成功的卷积神经网络应用
  • AlexNet:类似LeNet,但更深更大。使用了层叠的卷积层来抓取特征(通常是一个卷积层马上一个max pooling层)
  • ZF Net:增加了中间卷积层的尺寸,让第一层的stride和filter size更小。
  • GoogLeNet:减少parameters数量,最后一层用max pooling层代替了全连接层,更重要的是Inception-v4模块的使用。
  • VGGNet:只使用3x3 卷积层和2x2 pooling层从头到尾堆叠。
  • ResNet:引入了跨层连接和batch normalization。
  • DenseNet:将跨层连接从头进行到尾。

总结一下:这些结构的发展趋势有:

  • 使用small filter size的卷积层和pooling
  • 去掉parameters过多的全连接层
  • Inception(稍后会对其中的细节进行说明)
  • 跳层连接

不变性的满足

接下来会谈谈我个人的,对于画面不变性是如何被卷积神经网络满足的想法。 同时结合不变性,对上面提到的结构发展的重要变动进行直觉上的解读。

需要明白的是为什么加入不变性可以提高网络表现。 并不是因为我们用了更炫酷的处理方式,而是加入了先验知识,无需从零开始用数据学习,节省了训练所需数据量。 思考表现提高的原因一定要从训练所需要的数据量切入。 提出满足新的不变性特点的神经网络是计算机视觉的一个主要研究方向。

平移不变性

可以说卷积神经网络最初引入局部连接和空间共享,就是为了满足平移不变性。

<img src="https://pic4.zhimg.com/50/v2-1aac56212d5d143a006d569318e3ee8b_hd.png" data-caption="" data-rawwidth="550" data-rawheight="136" class="origin_image zh-lightbox-thumb" width="550" data-original="https://pic4.zhimg.com/v2-1aac56212d5d143a006d569318e3ee8b_r.png">


因为空间共享,在不同位置的同一形状就可以被等价识别,所以不需要对每个位置都进行学习。

<img src="https://pic2.zhimg.com/50/v2-18c11c6f485e9f1bbc9a50eb3d248439_hd.png" data-caption="" data-rawwidth="411" data-rawheight="374" class="content_image" width="411">


旋转和视角不变性

个人觉得卷积神经网络克服这一不变性的主要手段还是靠大量的数据。 并没有明确加入“旋转和视角不变性”的先验特性。

<img src="https://pic2.zhimg.com/50/v2-0ce892f8b247f2b48a76cc57cbcba41d_hd.png" data-caption="" data-rawwidth="552" data-rawheight="250" class="origin_image zh-lightbox-thumb" width="552" data-original="https://pic2.zhimg.com/v2-0ce892f8b247f2b48a76cc57cbcba41d_r.png">


Deformable Convolutional Networks似乎是对此变性进行了进行增强。

尺寸不变性

与平移不变性不同,最初的卷积网络并没有明确照顾尺寸不变性这一特点。

我们知道filter的size是事先选择的,而不同的尺寸所寻找的形状(概念)范围不同。

从直观上思考,如果选择小范围,再一步步通过组合,仍然是可以得到大范围的形状。 如3x3尺寸的形状都是可以由2x2形状的图形组合而成。所以形状的尺寸不变性对卷积神经网络而言并不算问题。 这恐怕ZF Net让第一层的stride和filter size更小,VGGNet将所有filter size都设置成3x3仍可以得到优秀结果的一个原因。

但是,除了形状之外,很多概念的抓取通常需要考虑一个像素与周边更多像素之间的关系后得出。 也就是说5x5的filter也是有它的优点。 同时,小尺寸的堆叠需要很多个filters来共同完成,如果需要抓取的形状恰巧在5x5的范围,那么5x5会比3x3来的更有效率。 所以一次性使用多个不同filter size来抓取多个范围不同的概念是一种顺理成章的想法,而这个也就是Inception。 可以说Inception是为了尺寸不变性而引入的一个先验知识。

Inception

下图是Inception的结构,尽管也有不同的版本,但是其动机都是一样的:消除尺寸对于识别结果的影响,一次性使用多个不同filter size来抓取多个范围不同的概念,并让网络自己选择需要的特征。

你也一定注意到了蓝色的1x1卷积,撇开它,先看左边的这个结构。

输入(可以是被卷积完的长方体输出作为该层的输入)进来后,通常我们可以选择直接使用像素信息(1x1卷积)传递到下一层,可以选择3x3卷积,可以选择5x5卷积,还可以选择max pooling的方式downsample刚被卷积后的feature maps。 但在实际的网络设计中,究竟该如何选择需要大量的实验和经验的。 Inception就不用我们来选择,而是将4个选项给神经网络,让网络自己去选择最合适的解决方案。

接下来我们再看右边的这个结构,多了很多蓝色的1x1卷积。 这些1x1卷积的作用是为了让网络根据需要能够更灵活的控制数据的depth的。

<img src="https://pic2.zhimg.com/50/v2-9692631d087622f1b34c80055f13fac5_hd.png" data-caption="" data-rawwidth="983" data-rawheight="311" class="origin_image zh-lightbox-thumb" width="983" data-original="https://pic2.zhimg.com/v2-9692631d087622f1b34c80055f13fac5_r.png">


1x1卷积核

如果卷积的输出输入都只是一个平面,那么1x1卷积核并没有什么意义,它是完全不考虑像素与周边其他像素关系。 但卷积的输出输入是长方体,所以1x1卷积实际上是对每个像素点,在不同的channels上进行线性组合(信息整合),且保留了图片的原有平面结构,调控depth,从而完成升维或降维的功能。

如下图所示,如果选择2个filters的1x1卷积层,那么数据就从原本的depth 3 降到了2。若用4个filters,则起到了升维的作用。

这就是为什么上面Inception的4个选择中都混合一个1x1卷积,如右侧所展示的那样。 其中,绿色的1x1卷积本身就1x1卷积,所以不需要再用另一个1x1卷积。 而max pooling用来去掉卷积得到的Feature Map中的冗余信息,所以出现在1x1卷积之前,紧随刚被卷积后的feature maps。(由于没做过实验,不清楚调换顺序会有什么影响。)

<img src="https://pic1.zhimg.com/50/v2-59429b22ac90930c502736b33db0d8e0_hd.png" data-caption="" data-rawwidth="643" data-rawheight="517" class="origin_image zh-lightbox-thumb" width="643" data-original="https://pic1.zhimg.com/v2-59429b22ac90930c502736b33db0d8e0_r.png">


跳层连接

前馈神经网络也好,卷积神经网络也好,都是一层一层逐步变换的,不允许跳层组合。 但现实中是否有跳层组合的现象?

比如说我们在判断一个人的时候,很多时候我们并不是观察它的全部,或者给你的图片本身就是残缺的。 这时我们会靠单个五官,外加这个人的着装,再加他的身形来综合判断这个人,如下图所示。 这样,即便图片本身是残缺的也可以很好的判断它是什么。 这和前馈神经网络的先验知识不同,它允许不同层级之间的因素进行信息交互、综合判断。

残差网络就是拥有这种特点的神经网络。大家喜欢用identity mappings去解释为什么残差网络更优秀。 这里我只是提供了一个以先验知识的角度去理解的方式。 需要注意的是每一层并不会像我这里所展示的那样,会形成明确的五官层。 只是有这样的组合趋势,实际无法保证神经网络到底学到了什么内容。

<img src="https://pic4.zhimg.com/50/v2-40fb6ab7bf89ce43af1c52e673da65eb_hd.png" data-caption="" data-rawwidth="509" data-rawheight="507" class="origin_image zh-lightbox-thumb" width="509" data-original="https://pic4.zhimg.com/v2-40fb6ab7bf89ce43af1c52e673da65eb_r.png">


用下图举一个更易思考的例子。 图形1,2,3,4,5,6是第一层卷积层抓取到的概念。 图形7,8,9是第二层卷积层抓取到的概念。 图形7,8,9是由1,2,3,4,5,6的基础上组合而成的。

但当我们想要探测的图形10并不是单纯的靠图形7,8,9组成,而是第一个卷积层的图形6和第二个卷积层的8,9组成的话,不允许跨层连接的卷积网络不得不用更多的filter来保持第一层已经抓取到的图形信息。并且每次传递到下一层都需要学习那个用于保留前一层图形概念的filter的权重。 当层数变深后,会越来越难以保持,还需要max pooling将冗余信息去掉。

一个合理的做法就是直接将上一层所抓取的概念也跳层传递给下下一层,不用让其每次都重新学习。 就好比在编程时构建了不同规模的functions。 每个function我们都是保留,而不是重新再写一遍。提高了重用性。

同时,因为ResNet使用了跳层连接的方式。也不需要max pooling对保留低层信息时所产生的冗余信息进行去除。

<img src="https://pic3.zhimg.com/50/v2-87fc4b7449d751c59977c3a368ae6f7e_hd.png" data-caption="" data-rawwidth="484" data-rawheight="436" class="origin_image zh-lightbox-thumb" width="484" data-original="https://pic3.zhimg.com/v2-87fc4b7449d751c59977c3a368ae6f7e_r.png">


Inception中的第一个1x1的卷积通道也有类似的作用,但是1x1的卷积仍有权重需要学习。 并且Inception所使用的结合方式是concatenate的合并成一个更大的向量的方式,而ResNet的结合方式是sum。 两个结合方式各有优点。 concatenate当需要用不同的维度去组合成新观念的时候更有益。 而sum则更适用于并存的判断。比如既有油头发,又有胖身躯,同时穿着常年不洗的牛仔裤,三个不同层面的概念并存时,该人会被判定为程序员的情况。 又比如双向LSTM中正向和逆向序列抓取的结合常用相加的方式结合。在语音识别中,这表示既可以正向抓取某种特征,又可以反向抓取另一种特征。当两种特征同时存在时才会被识别成某个特定声音。

在下图的ResNet中,前一层的输入会跳过部分卷积层,将底层信息传递到高层。

<img src="https://pic4.zhimg.com/50/v2-d3fd09f011583932b832ea64f78233af_hd.png" data-caption="" data-rawwidth="317" data-rawheight="615" class="content_image" width="317">


在下图的DenseNet中,底层信息会被传递到所有的后续高层。

<img src="https://pic1.zhimg.com/50/v2-0bebba2947e5e968a93e6def0ae5d00c_hd.png" data-caption="" data-rawwidth="602" data-rawheight="389" class="origin_image zh-lightbox-thumb" width="602" data-original="https://pic1.zhimg.com/v2-0bebba2947e5e968a93e6def0ae5d00c_r.png">


后续

随着时间推移,各个ResNet,GoogLeNet等框架也都在原有的基础上进行了发展和改进。 但基本都是上文描述的概念的组合使用加上其他的tricks。

如下图所展示的,加入跳层连接的Inception-ResNet。

<img src="https://i-blog.csdnimg.cn/blog_migrate/69c572eb4436adc312b41b1a039c4f93.jpeg" data-caption="" data-rawwidth="1820" data-rawheight="1086" class="origin_image zh-lightbox-thumb" width="1820" data-original="https://pic3.zhimg.com/v2-389496d1436895dfe43199a0f54c35ca_r.jpg">


但对我而言,

真正重要的是这些技巧对于各种不变性的满足。



深度学习通俗易懂教程专栏超智能体 - 知乎专栏

阅读列表:

  1. 深层神经网络:深层学习为何要“Deep”(上)(由于下篇写的并不通俗,不推荐阅读,用公开课代替)
  2. 反向传播算法实例:未编写
  3. 深度学习总览:公开课:深层神经网络设计理念
  4. 深度学习入门误区:知乎Live(公开课涵盖了Live的内容,若觉得作者辛苦也可参加。算了,还是不要参加了!)
  5. Tensorflow :TensorFlow整体把握
  6. 前馈神经网络(1):前馈神经网络--代码LV1
  7. 前馈神经网络(2):前馈神经网络--代码LV2
  8. 前馈神经网络(3):前馈神经网络--代码LV3
  9. 循环神经网络(1)循环神经网络--介绍
  10. 循环神经网络(2)循环神经网络--实现LSTM
  11. 循环神经网络(3)循环神经网络--scan实现LSTM
  12. 循环神经网络(4)循环神经网络--双向GRU
  13. 卷积神经网络(1)卷积神经网络--介绍


Part 1:图像识别任务


卷积神经网络,听起来像是计算机科学、生物学和数学的诡异组合,但它们已经成为计算机视觉领域中最具影响力的革新的一部分。神经网络在 2012 年崭露头角,Alex Krizhevsky 凭借它们赢得了那一年的 ImageNet 挑战赛(大体上相当于计算机视觉的年度奥林匹克),他把分类误差记录从 26% 降到了 15%,在当时震惊了世界。自那之后,大量公司开始将深度学习用作服务的核心。Facebook 将神经网络用于自动标注算法、谷歌将它用于图片搜索、亚马逊将它用于商品推荐、Pinterest 将它用于个性化主页推送、Instagram 将它用于搜索架构。

<img src="https://i-blog.csdnimg.cn/blog_migrate/24ce2458dfefaf03f5fefe1c6eb1d5f9.jpeg" data-rawwidth="640" data-rawheight="249" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-834043be6a015ef9d7cf04de0cf03cca_r.jpg">

然而,应用这些网络最经典最流行的案例是进行图像处理。在图像处理任务中,让我们看一下如何使用卷积神经网络进行图像分类。


问题空间


图像分类是对输入图像的操作,最终输出一组最好地描述了图像内容的分类(如猫、狗等)或分类的概率。对人类来说,识别是打出生便开始学习的技能之一,对成人来说更是信手拈来,毫不费力。我们只需一眼便能快速识别我们所处的环境以及环绕在我们身边的物体。当我们看到一张图片或是环看四周的时候,无需刻意观察,多数时候也能立即描述出场景特征并标记出每一个对象。快速识别不同模式、根据早前知识进行归纳、以及适应不同的图像环境一直都是人类的专属技能,机器尚未享有。

<img src="https://i-blog.csdnimg.cn/blog_migrate/b2014be90d4cf5376511259d681a8f9c.jpeg" data-rawwidth="636" data-rawheight="222" class="origin_image zh-lightbox-thumb" width="636" data-original="https://pic3.zhimg.com/v2-a4552450f9ca496886c48cdd44475cce_r.jpg">

输入与输出


当计算机看到一张图像(输入一张图像)时,它看的是一大堆像素值。根据图片的分辨率和尺寸,它将看到一个 32 x 32 x 3 的数组(3 指代的是 RGB 值)。为了讲清楚这一点,假设我们有一张 JPG 格式的 480 x 480 大小的彩色图片,那么它对应的数组就有 480 x 480 x 3 个元素。其中每个数字的值从 0 到 255 不等,其描述了对应那一点的像素灰度。当我们人类对图像进行分类时,这些数字毫无用处,可它们却是计算机可获得的唯一输入。其中的思想是:当你提供给计算机这一数组后,它将输出描述该图像属于某一特定分类的概率的数字(比如:80% 是猫、15% 是狗、5% 是鸟)。


我们想要计算机做什么


现在我们知道了问题所在以及输入与输出,就该考虑如何处理了。我们想要计算机能够区分开所有提供给它的图片,以及搞清楚猫猫狗狗各自的特有特征。这也是我们人类的大脑中不自觉进行着的过程。当我们看到一幅狗的图片时,如果有诸如爪子或四条腿之类的明显特征,我们便能将它归类为狗。同样地,计算机也可以通过寻找诸如边缘和曲线之类的低级特点来分类图片,继而通过一系列卷积层级建构出更为抽象的概念。这是 CNN(卷积神经网络)工作方式的大体概述,下面是具体细节。


生物学连接


首先介绍些背景。当你第一次听到卷积神经网络这一术语,可能会联想到神经科学或生物学,那就对了。可以这样说。CNN 的确是从视觉皮层的生物学上获得启发的。视觉皮层有小部分细胞对特定部分的视觉区域敏感。Hubel 和 Wiesel 于 1962 年进行的一项有趣的试验详细说明了这一观点,他们验证出大脑中的一些个体神经细胞只有在特定方向的边缘存在时才能做出反应(即放电)。例如,一些神经元只对垂直边缘兴奋,另一些对水平或对角边缘兴奋。Hubel 和 Wisesl 发现所有这些神经元都以柱状结构的形式进行排列,而且一起工作才能产生视觉感知。这种一个系统中的特定组件有特定任务的观点(视觉皮层的神经元细胞寻找特定特征)在机器中同样适用,这就是 CNN 的基础。


结构


回到细节上来。更为详细的 CNN 工作概述指的是你挑一张图像,让它历经一系列卷积层、非线性层、池化(下采样(downsampling))层和完全连接层,最终得到输出。正如之前所说,输出可以是最好地描述了图像内容的一个单独分类或一组分类的概率。如今,难点在于理解其中每一层的工作方法。我们先来看最重要的部分。


第一层——数学部分


CNN 的第一层通常是卷积层(Convolutional Layer)。首先需要了解卷积层的输入内容是什么。如上所述,输入内容为一个 32 x 32 x 3 的像素值数组。现在,解释卷积层的最佳方法是想象有一束手电筒光正从图像的左上角照过。假设手电筒光可以覆盖 5 x 5 的区域,想象一下手电筒光照过输入图像的所有区域。在机器学习术语中,这束手电筒被叫做过滤器(filter,有时候也被称为神经元(neuron)或核(kernel)),被照过的区域被称为感受野(receptive field)。过滤器同样也是一个数组(其中的数字被称作权重或参数)。重点在于过滤器的深度必须与输入内容的深度相同(这样才能确保可以进行数学运算),因此过滤器大小为 5 x 5 x 3。现在,以过滤器所处在的第一个位置为例,即图像的左上角。当筛选值在图像上滑动(卷积运算)时,过滤器中的值会与图像中的原始像素值相乘(又称为计算点积)。这些乘积被加在一起(从数学上来说,一共会有 75 个乘积)。现在你得到了一个数字。切记,该数字只是表示过滤器位于图片左上角的情况。我们在输入内容上的每一位置重复该过程。(下一步将是将过滤器右移 1 单元,接着再右移 1 单元,以此类推。)输入内容上的每一特定位置都会产生一个数字。过滤器滑过所有位置后将得到一个 28 x 28 x 1 的数组,我们称之为激活映射(activation map)或特征映射(feature map)。之所以得到一个 28 x 28 的数组的原因在于,在一张 32 x 32 的输入图像上,5 x 5 的过滤器能够覆盖到 784 个不同的位置。这 784 个位置可映射为一个 28 x 28 的数组。


<img src="https://i-blog.csdnimg.cn/blog_migrate/7794e716e66e84a57fe904e15c412079.jpeg" data-rawwidth="640" data-rawheight="347" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-790a3d600c6b6208f3c7db27c393a1ea_r.jpg">

(注意:包括上图在内的一些图片来自于 Micheal Nielsen 的 「神经网络与深度学习( Neural Networks and Deep Learning)」一书。我强烈推荐这本书。这本书可免费在线浏览:Neural networks and deep learning


当我们使用两个而不是一个 5 x 5 x 3 的过滤器时,输出总量将会变成 28 x 28 x 2。采用的过滤器越多,空间维度( spatial dimensions)保留得也就越好。数学上而言,这就是卷积层上发生的事情。


第一层——高层次角度


不过,从高层次角度而言卷积是如何工作的?每个过滤器可以被看成是特征标识符( feature identifiers)。这里的特征指的是例如直边缘、原色、曲线之类的东西。想一想所有图像都共有的一些最简单的特征。假设第一组过滤器是 7 x 7 x 3 的曲线检测器。(在这一节,为了易于分析,暂且忽略该过滤器的深度为 3 个单元,只考虑过滤器和图像的顶层层面。)作为曲线过滤器,它将有一个像素结构,在曲线形状旁时会产生更高的数值(切记,我们所讨论的过滤器不过是一组数值!)

<img src="https://pic4.zhimg.com/50/v2-4e15bce4b402176ce8c6dca1538836d7_hd.png" data-rawwidth="624" data-rawheight="278" class="origin_image zh-lightbox-thumb" width="624" data-original="https://pic4.zhimg.com/v2-4e15bce4b402176ce8c6dca1538836d7_r.png">

左图:过滤器的像素表示;右图:曲线检测器过滤器的可视化;对比两图可以看到数值和形状的对应


回到数学角度来看这一过程。当我们将过滤器置于输入内容的左上角时,它将计算过滤器和这一区域像素值之间的点积。拿一张需要分类的照片为例,将过滤器放在它的左上角。

<img src="https://pic2.zhimg.com/50/v2-a7a8f5b74d66f7b5389f9c17a1417c09_hd.png" data-rawwidth="640" data-rawheight="227" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-a7a8f5b74d66f7b5389f9c17a1417c09_r.png">切记,我们要做的是将过滤器与图像的原始像素值相乘。切记,我们要做的是将过滤器与图像的原始像素值相乘。

<img src="https://pic4.zhimg.com/50/v2-f1c852e5da0df5407565aa5b0f78fe43_hd.png" data-rawwidth="640" data-rawheight="241" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-f1c852e5da0df5407565aa5b0f78fe43_r.png">

左图:感受野的可视化;右图:感受野的像素表示 * 过滤器的像素表示


简单来说,如果输入图像上某个形状看起来很像过滤器表示的曲线,那么所有点积加在一起将会得出一个很大的值!让我们看看移动过滤器时会发生什么。

<img src="https://pic4.zhimg.com/50/v2-4c637624f3f01ba910736784547c37db_hd.png" data-rawwidth="640" data-rawheight="224" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-4c637624f3f01ba910736784547c37db_r.png">

这个值小了很多!这是因为图像的这一部分和曲线检测器过滤器不存在对应。记住,这个卷积层的输出是一个激活映射(activation map)。因此,在这个带有一个过滤器卷积的例子里(当筛选值为曲线检测器),激活映射将会显示出图像里最像曲线的区域。在该例子中,28 x 28 x 1 的激活映射的左上角的值为 6600。高数值意味着很有可能是输入内容中的曲线激活了过滤器。激活地图右上角的值将会是 0,因为输入内容中没有任何东西能激活过滤器(更简单地说,原始图片中的这一区域没有任何曲线)。这仅仅是一组检测右弯曲线的过滤器。还有其它检测左弯曲线或直线边缘的过滤器。过滤器越多,激活映射的深度越大,我们对输入内容的了解也就越多。


声明:我在本小节中描绘的过滤器(filter)只是为了描述卷积中的数学过程。在下图中你可以看到训练后的网络中第一个卷积层的过滤器的实际可视化。尽管如此,主要观点仍旧不变。当在输入内容中寻找特定特征时,第一层上的过滤器在输入图像上进行卷积运算和「激活」(即计算高数值)。


<img src="https://i-blog.csdnimg.cn/blog_migrate/8b65495b3982312e2170c1925a7d9e15.jpeg" data-rawwidth="270" data-rawheight="277" class="content_image" width="270">

上图来自于斯坦福大学由 Andrej Karpathy 和 Justin Johnson 授课的 CS 231N 课程,推荐给渴望更深层理解 CNN 的人们:CS231n: Convolutional Neural Networks for Visual Recognition


网络中的更深处


在传统卷积神经网络架构中,卷积层之间还有其它类型的层。我强烈建议有兴趣的人阅读和它们有关的材料,并理解相应的功能和作用;但总的来说,它们提供的非线性和维度保留有助于提高网络的稳健性(robustness)并控制过拟合。一个典型的 CNN 结构看起来是这样的:


<img src="https://pic4.zhimg.com/50/v2-afa8132cdb9958051f102657335ac68f_hd.png" data-rawwidth="639" data-rawheight="46" class="origin_image zh-lightbox-thumb" width="639" data-original="https://pic4.zhimg.com/v2-afa8132cdb9958051f102657335ac68f_r.png">

输入→卷积→ReLU→卷积→ReLU→池化→ReLU→卷积→ReLU→池化→全连接


我们稍后再来讨论关键的最后一层,先回顾一下学到了哪些。我们讨论了过滤器是如何在第一个卷积层检测特征的。它们检测边缘和曲线一类的低级特征。正如想象的那样,为了预测出图片内容的分类,网络需要识别更高级的特征,例如手、爪子与耳朵的区别。第一个卷积层的输出将会是一个 28 x 28 x 3 的数组(假设我们采用三个 5 x 5 x 3 的过滤器)。当我们进入另一卷积层时,第一个卷积层的输出便是第二个卷积层的输入。解释这一点有些困难。第一层的输入是原始图像,而第二卷积层的输入正是第一层输出的激活映射。也就是说,这一层的输入大体描绘了低级特征在原始图片中的位置。在此基础上再采用一组过滤器(让它通过第 2 个卷积层),输出将是表示了更高级的特征的激活映射。这类特征可以是半圆(曲线和直线的组合)或四边形(几条直线的组合)。随着进入网络越深和经过更多卷积层后,你将得到更为复杂特征的激活映射。在网络的最后,可能会有一些过滤器会在看到手写笔迹或粉红物体等时激活。如果你想知道更多关于可视化卷积网络中过滤器的内容,可以查看 Matt Zeiler 和 Rob Fergus 的一篇讨论该问题的颇为杰出的研究论文。在 YouTube 上,Jason Yosinski 有一段视频十分视觉化地呈现了这一过程(如下)。有趣的是,越深入网络,过滤器的感受野越大,意味着它们能够处理更大范围的原始输入内容(或者说它们可以对更大区域的像素空间产生反应)。


完全连接层


检测高级特征之后,网络最后的完全连接层就更是锦上添花了。简单地说,这一层处理输入内容(该输入可能是卷积层、ReLU 层或是池化层的输出)后会输出一个 N 维向量,N 是该程序必须选择的分类数量。例如,如果你想得到一个数字分类程序,如果有 10 个数字,N 就等于 10。这个 N 维向量中的每一数字都代表某一特定类别的概率。例如,如果某一数字分类程序的结果矢量是 [0 .1 .1 .75 0 0 0 0 0 .05],则代表该图片有 10% 的概率是 1、10% 的概率是 2、75% 的概率是 3、还有 5% 的概率是 9(注:还有其他表现输出的方式,这里只展示了 softmax 的方法)。完全连接层观察上一层的输出(其表示了更高级特征的激活映射)并确定这些特征与哪一分类最为吻合。例如,如果该程序预测某一图像的内容为狗,那么激活映射中的高数值便会代表一些爪子或四条腿之类的高级特征。同样地,如果程序测定某一图片的内容为鸟,激活映射中的高数值便会代表诸如翅膀或鸟喙之类的高级特征。大体上来说,完全连接层观察高级特征和哪一分类最为吻合和拥有怎样的特定权重,因此当计算出权重与先前层之间的点积后,你将得到不同分类的正确概率。

<img src="https://i-blog.csdnimg.cn/blog_migrate/a4c26c8f94c1e7b9a0bde1e161f15461.jpeg" data-rawwidth="640" data-rawheight="206" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-0d4e7aabbd235461330da8904cd20bb5_r.jpg">

训练(也就是:什么能让其有效)


下面是神经网络中的一个我尚未提及但却最为重要的部分。阅读过程中你可能会提出许多问题。第一卷积层中的滤波器是如何知道寻找边缘与曲线的?完全连接层怎么知道观察哪些激活图?每一层级的滤波器如何知道需要哪些值?计算机通过一个名为反向传播的训练过程来调整过滤器值(或权重)。


在探讨反向传播之前,我们首先必须回顾一下神经网络工作起来需要什么。在我们刚出生的时候,大脑一无所知。我们不晓得猫啊狗啊鸟啊都是些什么东西。与之类似的是 CNN 刚开始的时候,权重或过滤器值都是随机的。滤波器不知道要去寻找边缘和曲线。更高层的过滤器值也不知道要去寻找爪子和鸟喙。不过随着年岁的增长,父母和老师向我们介绍各式各样的图片并且一一作出标记。CNN 经历的便是一个介绍图片与分类标记的训练过程。在深入探讨之前,先设定一个训练集,在这里有上千张狗、猫、鸟的图片,每一张都依照内容被标记。下面回到反向传播的问题上来。


反向传播可分为四部分,分别是前向传导、损失函数、后向传导,以及权重更新。在前向传导中,选择一张 32×32×3 的数组训练图像并让它通过整个网络。在第一个训练样例上,由于所有的权重或者过滤器值都是随机初始化的,输出可能会是 [.1 .1 .1 .1 .1 .1 .1 .1 .1 .1],即一个不偏向任何数字的输出。一个有着这样权重的网络无法寻找低级特征,或者说是不能做出任何合理的分类。接下来是反向传播的损失函数部分。切记我们现在使用的是既有图像又有标记的训练数据。假设输入的第一张训练图片为 3,标签将会是 [0 0 0 1 0 0 0 0 0 0]。损失函数有许多种定义方法,常见的一种是 MSE (均方误差)。

<img src="https://pic2.zhimg.com/50/v2-1d99155e7d28ecc87c9207e1ec845e5d_hd.png" data-rawwidth="472" data-rawheight="63" class="origin_image zh-lightbox-thumb" width="472" data-original="https://pic2.zhimg.com/v2-1d99155e7d28ecc87c9207e1ec845e5d_r.png">假设变量 L 等同该数值。正如所料,前两张训练图片的损失将会极高。现在,我们直观地想一下。我们想要预测标记(卷积网络的输出)与训练标记相同(意味着网络预测正确)。为了做到这一点,我们想要将损失数量最小化。将其视为微积分优化问题的话,也就是说我们想要找出是哪部分输入(例子中的权重)直接导致了网络的损失(或错误)。假设变量 L 等同该数值。正如所料,前两张训练图片的损失将会极高。现在,我们直观地想一下。我们想要预测标记(卷积网络的输出)与训练标记相同(意味着网络预测正确)。为了做到这一点,我们想要将损失数量最小化。将其视为微积分优化问题的话,也就是说我们想要找出是哪部分输入(例子中的权重)直接导致了网络的损失(或错误)。

<img src="https://pic3.zhimg.com/50/v2-8920aa91f987f9b43c61d6755331e006_hd.png" data-rawwidth="640" data-rawheight="222" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-8920aa91f987f9b43c61d6755331e006_r.png">

这是一个 dL/dW 的数学等式,W 是特定层级的权重。我们接下来要做的是在网络中进行后向传导,测定出是哪部分权重导致了最大的损失,寻找调整方法并减少损失。一旦计算出该导数,将进行最后一步也就是权重更新。所有的过滤器的权重将会更新,以便它们顺着梯度方向改变。


<img src="https://pic4.zhimg.com/50/v2-277722f38cdc66537c2bffbda47a3617_hd.png" data-rawwidth="606" data-rawheight="99" class="origin_image zh-lightbox-thumb" width="606" data-original="https://pic4.zhimg.com/v2-277722f38cdc66537c2bffbda47a3617_r.png">学习速率是一个由程序员决定的参数。高学习速率意味着权重更新的动作更大,因此可能该模式将花费更少的时间收敛到最优权重。然而,学习速率过高会导致跳动过大,不够准确以致于达不到最优点。 学习速率是一个由程序员决定的参数。高学习速率意味着权重更新的动作更大,因此可能该模式将花费更少的时间收敛到最优权重。然而,学习速率过高会导致跳动过大,不够准确以致于达不到最优点。
<img src="https://pic1.zhimg.com/50/v2-112ee3cfba309c85245c3a2fd6d42a04_hd.png" data-rawwidth="640" data-rawheight="198" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic1.zhimg.com/v2-112ee3cfba309c85245c3a2fd6d42a04_r.png">

总的来说,前向传导、损失函数、后向传导、以及参数更新被称为一个学习周期。对每一训练图片,程序将重复固定数目的周期过程。一旦完成了最后训练样本上的参数更新,网络有望得到足够好的训练,以便层级中的权重得到正确调整。


测试


最后,为了检验 CNN 能否工作,我们准备不同的另一组图片与标记集(不能在训练和测试中使用相同的!)并让它们通过这个 CNN。我们将输出与实际情况(ground truth )相比较,看看网络是否有效!


企业如何使用 CNN


数据、数据、数据。数据越多的企业在竞争中越发彰显优势。你提供给网络的训练数据越多,你能进行的训练迭代也越多,紧接着权重更新也多,那么当用于产品时调整出的网络自然就好。Facebook (和 Instagram)可以使用它如今拥有的十几亿用户的图片,Pinterest 可以使用它站点上 500 亿花瓣的信息,谷歌可以使用搜索数据,亚马逊可以使用每天销售的数以百万计的商品数据。而你现在也知道它们使用数据背后的神奇之处了。


Part 2:卷积神经网络中的部分问题



引言


在这篇文章中,我们将更深入地介绍有关卷积神经网络(ConvNet)的详细情况。声明:我确实知道本文中一部分内容相当复杂,可以用一整篇文章进行介绍。但为了在保持全面性的同时保证简洁,我会在文章中相关位置提供一些更详细解释该相关主题的论文链接。


步幅和填充


好了,现在来看一下我们的卷积神经网络。还记得过滤器、感受野和卷积吗?很好。现在,要改变每一层的行为,有两个主要参数是我们可以调整的。选择了过滤器的尺寸以后,我们还需要选择步幅(stride)和填充(padding)。


步幅控制着过滤器围绕输入内容进行卷积计算的方式。在第一部分我们举的例子中,过滤器通过每次移动一个单元的方式对输入内容进行卷积。过滤器移动的距离就是步幅。在那个例子中,步幅被默认设置为1。步幅的设置通常要确保输出内容是一个整数而非分数。让我们看一个例子。想象一个 7 x 7 的输入图像,一个 3 x 3 过滤器(简单起见不考虑第三个维度),步幅为 1。这是一种惯常的情况。

<img src="https://pic4.zhimg.com/50/v2-504ba01c8af8e2d7d41957ddaa4fe6d3_hd.png" data-rawwidth="594" data-rawheight="236" class="origin_image zh-lightbox-thumb" width="594" data-original="https://pic4.zhimg.com/v2-504ba01c8af8e2d7d41957ddaa4fe6d3_r.png">还是老一套,对吧?看你能不能试着猜出如果步幅增加到 2,输出内容会怎么样。还是老一套,对吧?看你能不能试着猜出如果步幅增加到 2,输出内容会怎么样。

<img src="https://pic3.zhimg.com/50/v2-c4a7b49deda73e2b26232d12db7e77c6_hd.png" data-rawwidth="627" data-rawheight="247" class="origin_image zh-lightbox-thumb" width="627" data-original="https://pic3.zhimg.com/v2-c4a7b49deda73e2b26232d12db7e77c6_r.png">

所以,正如你能想到的,感受野移动了两个单元,输出内容同样也会减小。注意,如果试图把我们的步幅设置成 3,那我们就会难以调节间距并确保感受野与输入图像匹配。正常情况下,程序员如果想让接受域重叠得更少并且想要更小的空间维度(spatial dimensions)时,他们会增加步幅。


现在让我们看一下填充(padding)。在此之前,想象一个场景:当你把 5 x 5 x 3 的过滤器用在 32 x 32 x 3 的输入上时,会发生什么?输出的大小会是 28 x 28 x 3。注意,这里空间维度减小了。如果我们继续用卷积层,尺寸减小的速度就会超过我们的期望。在网络的早期层中,我们想要尽可能多地保留原始输入内容的信息,这样我们就能提取出那些低层的特征。比如说我们想要应用同样的卷积层,但又想让输出量维持为 32 x 32 x 3 。为做到这点,我们可以对这个层应用大小为 2 的零填充(zero padding)。零填充在输入内容的边界周围补充零。如果我们用两个零填充,就会得到一个 36 x 36 x 3 的输入卷。

<img src="https://pic3.zhimg.com/50/v2-16ad975f95ef7a45ab836fa563e73736_hd.png" data-rawwidth="640" data-rawheight="248" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-16ad975f95ef7a45ab836fa563e73736_r.png">

如果我们在输入内容的周围应用两次零填充,那么输入量就为 32×32×3。然后,当我们应用带有 3 个 5×5×3 的过滤器,以 1 的步幅进行处理时,我们也可以得到一个 32×32×3 的输出


如果你的步幅为 1,而且把零填充设置为

<img src="https://pic4.zhimg.com/50/v2-151ea0d356f24533867c018bec7c3127_hd.png" data-rawwidth="425" data-rawheight="52" class="origin_image zh-lightbox-thumb" width="425" data-original="https://pic4.zhimg.com/v2-151ea0d356f24533867c018bec7c3127_r.png">

K 是过滤器尺寸,那么输入和输出内容就总能保持一致的空间维度。


计算任意给定卷积层的输出的大小的公式是

<img src="https://pic1.zhimg.com/50/v2-47d83d1bb16072a57d5c1fbb49991d68_hd.png" data-rawwidth="302" data-rawheight="53" class="content_image" width="302">

其中 O 是输出尺寸,K 是过滤器尺寸,P 是填充,S 是步幅。


选择超参数


我们怎么知道要用多少层、多少卷积层、过滤器尺寸是多少、以及步幅和填充值多大呢?这些问题很重要,但又没有一个所有研究人员都在使用的固定标准。这是因为神经网络很大程度上取决于你的数据类型。图像的大小、复杂度、图像处理任务的类型以及其他更多特征的不同都会造成数据的不同。对于你的数据集,想出如何选择超参数的一个方法是找到能创造出图像在合适尺度上抽象的正确组合。


ReLU(修正线性单元)层


在每个卷积层之后,通常会立即应用一个非线性层(或激活层)。其目的是给一个在卷积层中刚经过线性计算操作(只是数组元素依次(element wise)相乘与求和)的系统引入非线性特征。过去,人们用的是像双曲正切和 S 型函数这样的非线性方程,但研究者发现 ReLU 层效果好得多,因为神经网络能够在准确度不发生明显改变的情况下把训练速度提高很多(由于计算效率增加)。它同样能帮助减轻梯度消失的问题——由于梯度以指数方式在层中消失,导致网络较底层的训练速度非常慢。ReLU 层对输入内容的所有值都应用了函数 f(x) = max(0, x)。用基本术语来说,这一层把所有的负激活(negative activation)都变为零。这一层会增加模型乃至整个神经网络的非线性特征,而且不会影响卷积层的感受野。


  • 参见 Geoffrey Hinton(即深度学习之父)的论文:Rectified Linear Units Improve Restricted Boltzmann Machines


池化层


在几个 ReLU 层之后,程序员也许会选择用一个池化层(pooling layer)。它同时也被叫做下采样(downsampling)层。在这个类别中,也有几种可供选择的层,最受欢迎的就是最大池化( max-pooling)。它基本上采用了一个过滤器(通常是 2x2 的)和一个同样长度的步幅。然后把它应用到输入内容上,输出过滤器卷积计算的每个子区域中的最大数字。

<img src="https://pic2.zhimg.com/50/v2-a944f0f847266c28ad93f2b6b9986e65_hd.png" data-rawwidth="640" data-rawheight="333" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-a944f0f847266c28ad93f2b6b9986e65_r.png">

带有 2×2 和过滤器的且步幅为 2 的最大池化的例子


池化层还有其他选择,比如平均池化(average pooling)和 L2-norm 池化 。这一层背后的直观推理是:一旦我们知道了原始输入(这里会有一个高激活值)中一个特定的特征,它与其它特征的相对位置就比它的绝对位置更重要。可想而知,这一层大幅减小了输入卷的空间维度(长度和宽度改变了,但深度没变)。这到达了两个主要目的。第一个是权重参数的数目减少到了75%,因此降低了计算成本。第二是它可以控制过拟合(overfitting)。这个术语是指一个模型与训练样本太过匹配了,以至于用于验证和检测组时无法产生出好的结果。出现过拟合的表现是一个模型在训练集能达到 100% 或 99% 的准确度,而在测试数据上却只有50%。


Dropout 层


如今,Dropout 层在神经网络有了非常明确的功能。上一节,我们讨论了经过训练后的过拟合问题:训练之后,神经网络的权重与训练样本太过匹配以至于在处理新样本的时候表现平平。Dropout 的概念在本质上非常简单。Dropout 层将「丢弃(drop out)」该层中一个随机的激活参数集,即在前向通过(forward pass)中将这些激活参数集设置为 0。简单如斯。既然如此,这些简单而且似乎不必要且有些反常的过程的好处是什么?在某种程度上,这种机制强制网络变得更加冗余。这里的意思是:该网络将能够为特定的样本提供合适的分类或输出,即使一些激活参数被丢弃。此机制将保证神经网络不会对训练样本「过于匹配」,这将帮助缓解过拟合问题。另外,Dropout 层只能在训练中使用,而不能用于测试过程,这是很重要的一点。


  • 参考 Geoffrey Hinton 的论文:Dropout: A Simple Way to Prevent Neural Networks from Overfitting


网络层中的网络


网络层中的网络指的是一个使用了 1 x 1 尺寸的过滤器的卷积层。现在,匆匆一瞥,你或许会好奇为何这种感受野大于它们所映射空间的网络层竟然会有帮助。然而,我们必须谨记 1x1 的卷积层跨越了特定深度,所以我们可以设想一个1 x 1 x N 的卷积层,此处 N 代表该层应用的过滤器数量。该层有效地使用 N 维数组元素依次相乘的乘法,此时 N 代表的是该层的输入的深度。


  • 参阅 Min Lin 的论文:Network In Network


分类、定位、检测、分割


本系列第一部分使用的案例中,我们观察了图像分类任务。这个过程是:获取输入图片,输出一套分类的类数(class number)。然而当我们执行类似目标定位的任务时,我们要做的不只是生成一个类标签,而是生成一个描述图片中物体suo所在位置的边界框。

<img src="https://i-blog.csdnimg.cn/blog_migrate/0e95b7d746d086804dda9639dc7e1a53.jpeg" data-rawwidth="640" data-rawheight="257" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-53c1e0def4fdc2119fd13f2656234ef7_r.jpg">

我们也有目标检测的任务,这需要图片上所有目标的定位任务都已完成。


因此,你将获得多个边界框和多个类标签。


最终,我们将执行目标分割的任务:我们需要输出类标签的同时输出图片中每个目标的轮廓。


<img src="https://i-blog.csdnimg.cn/blog_migrate/6b8497aab06370138492e99292c62f75.jpeg" data-rawwidth="640" data-rawheight="250" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-24822a554ee977795e0d0ab22eaa0ff2_r.jpg">

关于目标检测、定位、分割的论文有很多,这里就不一一列出了。


迁移学习


如今,深度学习领域一个常见的误解在于没有谷歌那样的巨量数据,你将没有希望创建一个有效的深度学习模型。尽管数据是创建网络中至关重要的部分,迁移学习的思路将帮助我们降低数据需求。迁移学习指的是利用预训练模型(神经网络的权重和参数都已经被其他人利用更大规模的数据集训练好了)并用自己的数据集将模型「微调」的过程。这种思路中预训练模型扮演着特征提取器的角色。你将移除网络的最后一层并用你自有的分类器置换(取决于你的问题空间)。然后冻结其他所有层的权重并正常训练该网络(冻结这些层意味着在梯度下降/最优化过程中保持权值不变)。


让我们探讨一下为什么做这项工作。比如说我们正在讨论的这个预训练模型是在 ImageNet (一个包含一千多个分类,一千四百万张图像的数据集)上训练的 。当我们思考神经网络的较低层时,我们知道它们将检测类似曲线和边缘这样的特征。现在,除非你有一个极为独特的问题空间和数据集,你的神经网络也会检测曲线和边缘这些特征。相比通过随机初始化权重训练整个网络,我们可以利用预训练模型的权重(并冻结)聚焦于更重要的层(更高层)进行训练。如果你的数据集不同于 ImageNet 这样的数据集,你必须训练更多的层级而只冻结一些低层的网络。


  • Yoshua Bengio (另外一个深度学习先驱 )论文:How transferable are features in deep neural networks?

  • Ali Sharif Razavian 论文:CNN Features off-the-shelf: an Astounding Baseline for Recognition

  • Jeff Donahue 论文:DeCAF: A Deep Convolutional Activation Feature for Generic Visual Recognition


数据增强技术


现在我们对卷积网络中数据的重要性可能已经感到有些麻木了,所以我们来谈下如何利用一些简单的转换方法将你现有的数据集变得更大。正如我们之前所提及的,当计算机将图片当作输入时,它将用一个包含一列像素值的数组描述(这幅图)。若是图片左移一个像素。对你和我来说,这种变化是微不可察的。然而对计算机而已,这种变化非常显著:这幅图的类别和标签保持不变,数组却变化了。这种改变训练数据的数组表征而保持标签不变的方法被称作数据增强技术。这是一种人工扩展数据集的方法。人们经常使用的增强方法包括灰度变化、水平翻转、垂直翻转、随机编组、色值跳变、翻译、旋转等其他多种方法。通过利用这些训练数据的转换方法,你将获得两倍甚至三倍于原数据的训练样本。


深度 | 从入门到精通:卷积神经网络初学者指南(附论文)

该文是卷积神经网络--介绍,并假设你理解前馈神经网络。

如果不是,强烈建议你读完如何简单形象又有趣地讲解神经网络是什么? 后再来读该篇。

目录

  • 视觉感知
    • 画面识别是什么
    • 识别结果取决于什么
  • 图像表达
    • 画面识别的输入
    • 画面不变形
  • 前馈神经网络做画面识别的不足
  • 卷积神经网络做画面识别
    • 局部连接
    • 空间共享
    • 输出空间表达
    • Depth维的处理
    • Zero padding
    • 形状、概念抓取
    • 多filters
    • 非线性
    • 输出尺寸控制
    • 矩阵乘法执行卷积
    • Max pooling
    • 全连接层
    • 结构发展
  • 画面不变性的满足
    • 平移不变性
    • 旋转和视角不变性
    • 尺寸不变性
    • Inception的理解
    • 1x1卷积核理解
    • 跳层连接ResNet

视觉感知

一、画面识别是什么任务?

学习知识的第一步就是明确任务,清楚该知识的输入输出。卷积神经网络最初是服务于画面识别的,所以我们先来看看画面识别的实质是什么。

先观看几组动物与人类视觉的差异对比图。

1. 苍蝇的视觉和人的视觉的差异

<img src="https://i-blog.csdnimg.cn/blog_migrate/2152191d5bd327c98e722f453ae2d643.jpeg" data-caption="" data-rawwidth="384" data-rawheight="216" class="content_image" width="384"> <img src="https://pic2.zhimg.com/50/v2-4a0ea7ba42166b62bc4f42e8b150815d_hd.png" data-caption="" data-rawwidth="1280" data-rawheight="479" class="origin_image zh-lightbox-thumb" width="1280" data-original="https://pic2.zhimg.com/v2-4a0ea7ba42166b62bc4f42e8b150815d_r.png">


2. 蛇的视觉和人的视觉的差异

<img src="https://i-blog.csdnimg.cn/blog_migrate/b19180680fd0cc36773007e3aa1466bd.jpeg" data-caption="" data-rawwidth="384" data-rawheight="216" class="content_image" width="384"> <img src="https://pic4.zhimg.com/50/v2-3da84b5b80ba7a0d779284566f80be93_hd.png" data-caption="" data-rawwidth="1280" data-rawheight="479" class="origin_image zh-lightbox-thumb" width="1280" data-original="https://pic4.zhimg.com/v2-3da84b5b80ba7a0d779284566f80be93_r.png">


(更多对比图请参考链接

通过上面的两组对比图可以知道,即便是相同的图片经过不同的视觉系统,也会得到不同的感知。

这里引出一条知识:生物所看到的景象并非世界的原貌,而是长期进化出来的适合自己生存环境的一种感知方式。 蛇的猎物一般是夜间行动,所以它就进化出了一种可以在夜间也能很好观察的感知系统,感热。

任何视觉系统都是将图像反光与脑中所看到的概念进行关联。

<img src="https://pic4.zhimg.com/50/v2-2c82abd20c4e7c40f7f13f035b924b0b_hd.png" data-caption="" data-rawwidth="223" data-rawheight="97" class="content_image" width="223">


所以画面识别实际上并非识别这个东西客观上是什么,而是寻找人类的视觉关联方式,并再次应用。 如果我们不是人类,而是蛇类,那么画面识别所寻找的 就和现在的不一样。

画面识别实际上是寻找(学习)人类的视觉关联方式 ,并再次应用

二、图片被识别成什么取决于哪些因素?

下面用两张图片来体会识别结果取决于哪些因素。

1. 老妇与少女

<img src="https://i-blog.csdnimg.cn/blog_migrate/b6e3154b3bad36659665a19cf93eb646.jpeg" data-caption="" data-rawwidth="198" data-rawheight="255" class="content_image" width="198">


请观察上面这张图片,你看到的是老妇还是少女? 以不同的方式去观察这张图片会得出不同的答案。 图片可以观察成有大鼻子、大眼睛的老妇。也可以被观察成少女,但这时老妇的嘴会被识别成少女脖子上的项链,而老妇的眼睛则被识别为少女的耳朵。

2. 海豚与男女

<img src="https://i-blog.csdnimg.cn/blog_migrate/c80bc1fc015523c744a952153d66e35e.jpeg" data-caption="" data-rawwidth="394" data-rawheight="509" class="content_image" width="394">


上面这张图片如果是成人观察,多半看到的会是一对亲热的男女。倘若儿童看到这张图片,看到的则会是一群海豚(男女的轮廓是由海豚构造出的)。所以,识别结果受年龄,文化等因素的影响,换句话说:

图片被识别成什么不仅仅取决于图片本身,还取决于图片是如何被观察的。

图像表达

我们知道了“画面识别是从大量的(x,y)数据中寻找人类的视觉关联方式 ,并再次应用。 其x-是输入,表示所看到的东西y-输出,表示该东西是什么。

在自然界中,x是物体的反光,那么在计算机中,图像又是如何被表达和存储的呢?

<img src="https://pic2.zhimg.com/50/v2-d2859e5c486ed704492ab80079e99535_hd.gif" data-caption="" data-rawwidth="291" data-rawheight="290" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/7602331a767af1638c458a98510d824c.jpeg" class="content_image" width="291">


[from]

图像在计算机中是一堆按顺序排列的数字,数值为0到255。0表示最暗,255表示最亮。 你可以把这堆数字用一个长长的向量来表示,也就是tensorflow的mnist教程中784维向量的表示方式。 然而这样会失去平面结构的信息,为保留该结构信息,通常选择矩阵的表示方式:28x28的矩阵。

上图是只有黑白颜色的灰度图,而更普遍的图片表达方式是RGB颜色模型,即红(Red)、绿(Green)、蓝(Blue)三原色的色光以不同的比例相加,以产生多种多样的色光。

这样,RGB颜色模型中,单个矩阵就扩展成了有序排列的三个矩阵,也可以用三维张量去理解,其中的每一个矩阵又叫这个图片的一个channel。

在电脑中,一张图片是数字构成的“长方体”。可用 宽width, 高height, 深depth 来描述,如图。

<img src="https://pic1.zhimg.com/50/v2-0d24890b2e0d73f4ce4ad17ebfb2d0c4_hd.png" data-caption="" data-rawwidth="305" data-rawheight="252" class="content_image" width="305">


画面识别的输入 x是shape为(width, height, depth)的三维张量。

接下来要考虑的就是该如何处理这样的“数字长方体”。

画面不变性

在决定如何处理“数字长方体”之前,需要清楚所建立的网络拥有什么样的特点。 我们知道一个物体不管在画面左侧还是右侧,都会被识别为同一物体,这一特点就是不变性(invariance),如下图所示。

<img src="https://pic3.zhimg.com/50/v2-b9aed3dd68b9818561faa7d8ed24ea5a_hd.png" data-caption="" data-rawwidth="567" data-rawheight="769" class="origin_image zh-lightbox-thumb" width="567" data-original="https://pic3.zhimg.com/v2-b9aed3dd68b9818561faa7d8ed24ea5a_r.png">


我们希望所建立的网络可以尽可能的满足这些不变性特点。

为了理解卷积神经网络对这些不变性特点的贡献,我们将用不具备这些不变性特点的前馈神经网络来进行比较。

图片识别--前馈神经网络

方便起见,我们用depth只有1的灰度图来举例。 想要完成的任务是:在宽长为4x4的图片中识别是否有下图所示的“横折”。 图中,黄色圆点表示值为0的像素,深色圆点表示值为1的像素。 我们知道不管这个横折在图片中的什么位置,都会被认为是相同的横折。

<img src="https://pic2.zhimg.com/50/v2-18c11c6f485e9f1bbc9a50eb3d248439_hd.png" data-caption="" data-rawwidth="411" data-rawheight="374" class="content_image" width="411">


若训练前馈神经网络来完成该任务,那么表达图像的三维张量将会被摊平成一个向量,作为网络的输入,即(width, height, depth)为(4, 4, 1)的图片会被展成维度为16的向量作为网络的输入层。再经过几层不同节点个数的隐藏层,最终输出两个节点,分别表示“有横折的概率”和“没有横折的概率”,如下图所示。

<img src="https://pic2.zhimg.com/50/v2-2b411af47b1cad7b727bb676c847ce59_hd.png" data-caption="" data-rawwidth="499" data-rawheight="505" class="origin_image zh-lightbox-thumb" width="499" data-original="https://pic2.zhimg.com/v2-2b411af47b1cad7b727bb676c847ce59_r.png">


下面我们用数字(16进制)对图片中的每一个像素点(pixel)进行编号。 当使用右侧那种物体位于中间的训练数据来训练网络时,网络就只会对编号为5,6,9,a的节点的权重进行调节。 若让该网络识别位于右下角的“横折”时,则无法识别。

<img src="https://pic2.zhimg.com/50/v2-ce9919e4930c1f29241afec0538b2605_hd.png" data-caption="" data-rawwidth="816" data-rawheight="505" class="origin_image zh-lightbox-thumb" width="816" data-original="https://pic2.zhimg.com/v2-ce9919e4930c1f29241afec0538b2605_r.png">


解决办法是用大量物体位于不同位置的数据训练,同时增加网络的隐藏层个数从而扩大网络学习这些变体的能力。

然而这样做十分不效率,因为我们知道在左侧的“横折”也好,还是在右侧的“横折”也罢,大家都是“横折”。 为什么相同的东西在位置变了之后要重新学习?有没有什么方法可以将中间所学到的规律也运用在其他的位置? 换句话说,也就是让不同位置用相同的权重

图片识别--卷积神经网络

卷积神经网络就是让权重在不同位置共享的神经网络。

局部连接

在卷积神经网络中,我们先选择一个局部区域,用这个局部区域去扫描整张图片。 局部区域所圈起来的所有节点会被连接到下一层的一个节点上。

为了更好的和前馈神经网络做比较,我将这些以矩阵排列的节点展成了向量。 下图展示了被红色方框所圈中编号为0,1,4,5的节点是如何通过w_1,w_2,w_3,w_4连接到下一层的节点0上的。

<img src="https://pic1.zhimg.com/50/v2-e877b9099b1139c1a34b0bf66bf92aa4_hd.png" data-caption="" data-rawwidth="513" data-rawheight="514" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic1.zhimg.com/v2-e877b9099b1139c1a34b0bf66bf92aa4_r.png">


这个带有连接强弱的红色方框就叫做 filterkernelfeature detector。 而filter的范围叫做filter size,这里所展示的是2x2的filter size。

\left[ \begin{matrix} w_1&w_2\\ w_3&w_4\\ \end{matrix} \right] (1)

第二层的节点0的数值就是局部区域的线性组合,即被圈中节点的数值乘以对应的权重后相加。 用x表示输入值,y表示输出值,用图中标注数字表示角标,则下面列出了两种计算编号为0的输出值y_0的表达式。

注:在局部区域的线性组合后,也会和前馈神经网络一样,加上一个偏移量b_0

\begin{split} y_0 &= x_0*w_1 + x_1*w_2+ x_4*w_3+ x_5*w_4+b_0\\y_0 &= \left[ \begin{matrix} w_1&w_2& w_3&w_4 \end{matrix} \right] \cdot \left[ \begin{matrix} x_0\\ x_1\\ x_4\\ x_5\\ \end{matrix} \right]+b_0 \end{split} (2)

空间共享

当filter扫到其他位置计算输出节点y_i 时,w_1,w_2,w_3,w_4包括b_0是共用的。

下面这张动态图展示了当filter扫过不同区域时,节点的链接方式。 动态图的最后一帧则显示了所有连接。 可以注意到,每个输出节点并非像前馈神经网络中那样与全部的输入节点连接,而是部分连接。 这也就是为什么大家也叫前馈神经网络(feedforward neural network)为fully-connected neural network。 图中显示的是一步一步的移动filter来扫描全图,一次移动多少叫做stride。

<img src="https://pic1.zhimg.com/50/v2-4fd0400ccebc8adb2dffe24aac163e70_hd.gif" data-caption="" data-rawwidth="513" data-rawheight="514" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/84d912ca7f1819f0ce18f49a79655681.jpeg" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic1.zhimg.com/v2-4fd0400ccebc8adb2dffe24aac163e70_r.gif">


空间共享也就是卷积神经网络所引入的先验知识。

输出表达

如先前在图像表达中提到的,图片不用向量去表示是为了保留图片平面结构的信息。 同样的,卷积后的输出若用上图的排列方式则丢失了平面结构信息。 所以我们依然用矩阵的方式排列它们,就得到了下图所展示的连接。

<img src="https://pic2.zhimg.com/50/v2-e1691956fd1beb5d7a637924a1a73d91_hd.png" data-caption="" data-rawwidth="513" data-rawheight="514" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic2.zhimg.com/v2-e1691956fd1beb5d7a637924a1a73d91_r.png">


这也就是你们在网上所看到的下面这张图。在看这张图的时候请结合上图的连接一起理解,即输入(绿色)的每九个节点连接到输出(粉红色)的一个节点上的。

<img src="https://pic3.zhimg.com/50/v2-7fce29335f9b43bce1b373daa40cccba_hd.gif" data-caption="" data-rawwidth="526" data-rawheight="384" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/c648e567095fc1e076937488d17201bc.jpeg" class="origin_image zh-lightbox-thumb" width="526" data-original="https://pic3.zhimg.com/v2-7fce29335f9b43bce1b373daa40cccba_r.gif">


经过一个feature detector计算后得到的粉红色区域也叫做一个“Convolved Feature” 或 “Activation Map” 或 “Feature Map”。

Depth维的处理

现在我们已经知道了depth维度只有1的灰度图是如何处理的。 但前文提过,图片的普遍表达方式是下图这样有3个channels的RGB颜色模型。 当depth为复数的时候,每个feature detector是如何卷积的?

<img src="https://pic1.zhimg.com/50/v2-0d24890b2e0d73f4ce4ad17ebfb2d0c4_hd.png" data-caption="" data-rawwidth="305" data-rawheight="252" class="content_image" width="305">


现象:2x2所表达的filter size中,一个2表示width维上的局部连接数,另一个2表示height维上的局部连接数,并却没有depth维上的局部连接数,是因为depth维上并非局部,而是全部连接的。

在2D卷积中,filter在张量的width维, height维上是局部连接,在depth维上是贯串全部channels的。

类比:想象在切蛋糕的时候,不管这个蛋糕有多少层,通常大家都会一刀切到底,但是在长和宽这两个维上是局部切割。

下面这张图展示了,在depth为复数时,filter是如何连接输入节点到输出节点的。 图中红、绿、蓝颜色的节点表示3个channels。 黄色节点表示一个feature detector卷积后得到的Feature Map。 其中被透明黑框圈中的12个节点会被连接到黄黑色的节点上。

  • 在输入depth为1时:被filter size为2x2所圈中的4个输入节点连接到1个输出节点上。
  • 在输入depth为3时:被filter size为2x2,但是贯串3个channels后,所圈中的12个输入节点连接到1个输出节点上。
  • 在输入depth为n时:2x2xn个输入节点连接到1个输出节点上。
<img src="https://pic3.zhimg.com/50/v2-23db15ec3f783bbb5cf811711e46dbba_hd.png" data-caption="" data-rawwidth="302" data-rawheight="382" class="content_image" width="302">


(可从vectary在3D编辑下查看)

注意:三个channels的权重并不共享。 即当深度变为3后,权重也跟着扩增到了三组,如式子(3)所示,不同channels用的是自己的权重。 式子中增加的角标r,g,b分别表示red channel, green channel, blue channel的权重。

\left[ \begin{matrix} w_{r1}&w_{r2}\\ w_{r3}&w_{r4}\\ \end{matrix} \right], \left[ \begin{matrix} w_{g1}&w_{g2}\\ w_{g3}&w_{g4}\\ \end{matrix} \right], \left[ \begin{matrix} w_{b1}&w_{b2}\\ w_{b3}&w_{b4}\\ \end{matrix} \right] (3)

计算例子:用x_{r0}表示red channel的编号为0的输入节点,x_{g5}表示green channel编号为5个输入节点。x_{b1}表示blue channel。如式子(4)所表达,这时的一个输出节点实际上是12个输入节点的线性组合。

\begin{split} y_0 &= x_{r0}*w_{r1} + x_{r1}*w_{r2}+ x_{r4}*w_{r3}+ x_{r5}*w_{r4}+ x_{g0}*w_{g1} + x_{g1}*w_{g2}+ x_{g4}*w_{g3}+ x_{g5}*w_{g4}+ x_{b0}*w_{b1} + x_{b1}*w_{b2}+ x_{b4}*w_{b3}+ x_{b5}*w_{b4}+b_0\\y_0 &= \left[ \begin{matrix} w_{r1}&w_{r2}& w_{r3}&w_{r4} \end{matrix} \right] \cdot \left[ \begin{matrix} x_{r0}\\ x_{r1}\\ x_{r4}\\ x_{r5}\\ \end{matrix} \right] +\left[ \begin{matrix} w_{g1}&w_{g2}& w_{g3}&w_{g4} \end{matrix} \right] \cdot \left[ \begin{matrix} x_{g0}\\ x_{g1}\\ x_{g4}\\ x_{g5}\\ \end{matrix} \right]+\left[ \begin{matrix} w_{b1}&w_{b2}& w_{b3}&w_{b4} \end{matrix} \right] \cdot \left[ \begin{matrix} x_{b0}\\ x_{b1}\\ x_{b4}\\ x_{b5}\\ \end{matrix} \right]+b_0\end{split}(4)

当filter扫到其他位置计算输出节点y_i时,那12个权重在不同位置是共用的,如下面的动态图所展示。 透明黑框圈中的12个节点会连接到被白色边框选中的黄色节点上。

<img src="https://pic3.zhimg.com/50/v2-0bc83b72ef50099b70a10cc3ab528f62_hd.gif" data-caption="" data-rawwidth="326" data-rawheight="455" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/0bb18dfa8fe95c252604e622f1461d37.jpeg" class="content_image" width="326">


每个filter会在width维, height维上,以局部连接和空间共享,并贯串整个depth维的方式得到一个Feature Map。

Zero padding

细心的读者应该早就注意到了,4x4的图片被2x2的filter卷积后变成了3x3的图片,每次卷积后都会小一圈的话,经过若干层后岂不是变的越来越小? Zero padding就可以在这时帮助控制Feature Map的输出尺寸,同时避免了边缘信息被一步步舍弃的问题。

例如:下面4x4的图片在边缘Zero padding一圈后,再用3x3的filter卷积后,得到的Feature Map尺寸依然是4x4不变。

<img src="https://pic2.zhimg.com/50/v2-c1010eb5dcf032ea95eab495a45f9b31_hd.png" data-caption="" data-rawwidth="173" data-rawheight="173" class="content_image" width="173">


通常大家都想要在卷积时保持图片的原始尺寸。 选择3x3的filter和1的zero padding,或5x5的filter和2的zero padding可以保持图片的原始尺寸。 这也是为什么大家多选择3x3和5x5的filter的原因。 另一个原因是3x3的filter考虑到了像素与其距离为1以内的所有其他像素的关系,而5x5则是考虑像素与其距离为2以内的所有其他像素的关系。

尺寸:Feature Map的尺寸等于(input_size + 2 * padding_size − filter_size)/stride+1。

注意:上面的式子是计算width或height一维的。padding_size也表示的是单边补零的个数。例如(4+2-3)/1+1 = 4,保持原尺寸。

不用去背这个式子。其中(input_size + 2 * padding_size)是经过Zero padding扩充后真正要卷积的尺寸。 减去 filter_size后表示可以滑动的范围。 再除以可以一次滑动(stride)多少后得到滑动了多少次,也就意味着得到了多少个输出节点。 再加上第一个不需要滑动也存在的输出节点后就是最后的尺寸。

形状、概念抓取

知道了每个filter在做什么之后,我们再来思考这样的一个filter会抓取到什么样的信息。

我们知道不同的形状都可由细小的“零件”组合而成的。比如下图中,用2x2的范围所形成的16种形状可以组合成格式各样的“更大”形状。

卷积的每个filter可以探测特定的形状。又由于Feature Map保持了抓取后的空间结构。若将探测到细小图形的Feature Map作为新的输入再次卷积后,则可以由此探测到“更大”的形状概念。 比如下图的第一个“大”形状可由2,3,4,5基础形状拼成。第二个可由2,4,5,6组成。第三个可由6,1组成。

<img src="https://pic1.zhimg.com/50/v2-f53f6ac43abd2555cfbbba6ea7fdc0e4_hd.png" data-caption="" data-rawwidth="484" data-rawheight="291" class="origin_image zh-lightbox-thumb" width="484" data-original="https://pic1.zhimg.com/v2-f53f6ac43abd2555cfbbba6ea7fdc0e4_r.png">


除了基础形状之外,颜色、对比度等概念对画面的识别结果也有影响。卷积层也会根据需要去探测特定的概念。

可以从下面这张图中感受到不同数值的filters所卷积过后的Feature Map可以探测边缘,棱角,模糊,突出等概念。

<img src="https://pic1.zhimg.com/50/v2-644d108587a6ce7fa471ede5d2e11e98_hd.png" data-caption="" data-rawwidth="342" data-rawheight="562" class="content_image" width="342">


[from]

如我们先前所提,图片被识别成什么不仅仅取决于图片本身,还取决于图片是如何被观察的。

而filter内的权重矩阵W是网络根据数据学习得到的,也就是说,我们让神经网络自己学习以什么样的方式去观察图片。

拿老妇与少女的那幅图片举例,当标签是少女时,卷积网络就会学习抓取可以成少女的形状、概念。 当标签是老妇时,卷积网络就会学习抓取可以成老妇的形状、概念。

下图展现了在人脸识别中经过层层的卷积后,所能够探测的形状、概念也变得越来越抽象和复杂。

<img src="https://i-blog.csdnimg.cn/blog_migrate/3ab2c504ba69e38c6e26885c5158a59a.jpeg" data-caption="" data-rawwidth="366" data-rawheight="546" class="content_image" width="366">


卷积神经网络会尽可能寻找最能解释训练数据的抓取方式。

多filters

每个filter可以抓取探测特定的形状的存在。 假如我们要探测下图的长方框形状时,可以用4个filters去探测4个基础“零件”。

<img src="https://pic1.zhimg.com/50/v2-6df64fccc9a8e2f696626f85233acb3c_hd.png" data-caption="" data-rawwidth="123" data-rawheight="127" class="content_image" width="123">


<img src="https://pic4.zhimg.com/50/v2-65461a21a909eca2e190c54db59a2c8f_hd.png" data-caption="" data-rawwidth="315" data-rawheight="82" class="content_image" width="315">


因此我们自然而然的会选择用多个不同的filters对同一个图片进行多次抓取。 如下图(动态图过大,如果显示不出,请看到该链接观看),同一个图片,经过两个(红色、绿色)不同的filters扫描过后可得到不同特点的Feature Maps。 每增加一个filter,就意味着你想让网络多抓取一个特征。

<img src="https://pic2.zhimg.com/50/v2-c7f1ea1d42820b4de30bd548c3986ecd_hd.gif" data-caption="" data-rawwidth="212" data-rawheight="120" data-thumbnail="https://i-blog.csdnimg.cn/blog_migrate/f0555cb14498d2418222f074797f420d.jpeg" class="content_image" width="212">


[from]

这样卷积层的输出也不再是depth为1的一个平面,而是和输入一样是depth为复数的长方体。

如下图所示,当我们增加一个filter(紫色表示)后,就又可以得到一个Feature Map。 将不同filters所卷积得到的Feature Maps按顺序堆叠后,就得到了一个卷积层的最终输出。

<img src="https://pic1.zhimg.com/50/v2-d11e1d2f2c41b6df713573f8155bc324_hd.png" data-caption="" data-rawwidth="1271" data-rawheight="629" class="origin_image zh-lightbox-thumb" width="1271" data-original="https://pic1.zhimg.com/v2-d11e1d2f2c41b6df713573f8155bc324_r.png">


卷积层的输入是长方体,输出也是长方体。

这样卷积后输出的长方体可以作为新的输入送入另一个卷积层中处理。

加入非线性

和前馈神经网络一样,经过线性组合和偏移后,会加入非线性增强模型的拟合能力。

将卷积所得的Feature Map经过ReLU变换(elementwise)后所得到的output就如下图所展示。

<img src="https://pic3.zhimg.com/50/v2-54a469b2873542e75abf2bc5d8fcaa1a_hd.png" data-caption="" data-rawwidth="748" data-rawheight="280" class="origin_image zh-lightbox-thumb" width="748" data-original="https://pic3.zhimg.com/v2-54a469b2873542e75abf2bc5d8fcaa1a_r.png">


[from]

输出长方体

现在我们知道了一个卷积层的输出也是一个长方体。 那么这个输出长方体的(width, height, depth)由哪些因素决定和控制。

这里直接用CS231n的Summary:

<img src="https://pic1.zhimg.com/50/v2-a9983c3cee935b68c73965bc1abe268c_hd.png" data-caption="" data-rawwidth="383" data-rawheight="376" class="content_image" width="383">


计算例子:请体会CS231n的Convolution Demo部分的演示。

矩阵乘法执行卷积

如果按常规以扫描的方式一步步计算局部节点和filter的权重的点乘,则不能高效的利用GPU的并行能力。 所以更普遍的方法是用两个大矩阵的乘法来一次性囊括所有计算。

因为卷积层的每个输出节点都是由若干个输入节点的线性组合所计算。 因为输出的节点个数是W_2 \times H_2\times D_2,所以就有W_2 \times H_2\times D_2个线性组合。

读过我写的线性代数教程的读者请回忆,矩阵乘矩阵的意义可以理解为批量的线性组合按顺序排列。 其中一个矩阵所表示的信息是多组权重,另一个矩阵所表示的信息是需要进行组合的向量。 大家习惯性的把组成成分放在矩阵乘法的右边,而把权重放在矩阵乘法的左边。 所以这个大型矩阵乘法可以用W_{row}\cdot X_{col}表示,其中W_{row}X_{col}都是矩阵。

<img src="https://pic1.zhimg.com/50/v2-11a4d56793af815eb2b4585d64aec178_hd.png" data-caption="" data-rawwidth="551" data-rawheight="136" class="origin_image zh-lightbox-thumb" width="551" data-original="https://pic1.zhimg.com/v2-11a4d56793af815eb2b4585d64aec178_r.png">


卷积的每个输出是由局部的输入节点和对应的filter权重展成向量后所计算的,如式子(2)。 那么W_{row}中的每一行则是每个filter的权重,有F\cdot F \cdot D_1个; 而X_{col}的每一列是所有需要进行组合的节点(上面的动态图中被黑色透明框圈中的节点),也有F\cdot F \cdot D_1个。X_{col}的列的个数则表示每个filter要滑动多少次才可以把整个图片扫描完,有W_2\cdot H_2次。 因为我们有多个filters,W_{row}的行的个数则是filter的个数K

最后我们得到:

W_{row} \in R^{K \times F\cdot F \cdot D_1}

X_{col} \in R^{F\cdot F \cdot D_1 \times W_2\cdot H_2}

W_{row}\cdot X_{col} \in R^{K \times W_2\cdot H_2}

当然矩阵乘法后需要将W_{row}\cdot X_{col}整理成形状为W_2 \times H_2\times D_2的三维张量以供后续处理(如再送入另一个卷积层)。X_{col}则也需要逐步的局部滑动图片,最后堆叠构成用于计算矩阵乘法的形式。

Max pooling

在卷积后还会有一个pooling的操作,尽管有其他的比如average pooling等,这里只提max pooling。

max pooling的操作如下图所示:整个图片被不重叠的分割成若干个同样大小的小块(pooling size)。每个小块内只取最大的数字,再舍弃其他节点后,保持原有的平面结构得出output。

<img src="https://i-blog.csdnimg.cn/blog_migrate/04a2dc413ef193903baf7c9c5071d312.jpeg" data-caption="" data-rawwidth="787" data-rawheight="368" class="origin_image zh-lightbox-thumb" width="787" data-original="https://pic1.zhimg.com/v2-1a4b2a3795d8f073e921d766e70ce6ec_r.jpg">


[from]

max pooling在不同的depth上是分开执行的,且不需要参数控制。 那么问题就max pooling有什么作用?部分信息被舍弃后难道没有影响吗?

<img src="https://i-blog.csdnimg.cn/blog_migrate/077b5feae096af9bf3ca526ea5541380.jpeg" data-caption="" data-rawwidth="514" data-rawheight="406" class="origin_image zh-lightbox-thumb" width="514" data-original="https://pic4.zhimg.com/v2-cd717414dcf32dac4df73c00f1e7c6c3_r.jpg">


[from]

Max pooling的主要功能是downsampling,却不会损坏识别结果。 这意味着卷积后的Feature Map中有对于识别物体不必要的冗余信息。 那么我们就反过来思考,这些“冗余”信息是如何产生的。

直觉上,我们为了探测到某个特定形状的存在,用一个filter对整个图片进行逐步扫描。但只有出现了该特定形状的区域所卷积获得的输出才是真正有用的,用该filter卷积其他区域得出的数值就可能对该形状是否存在的判定影响较小。 比如下图中,我们还是考虑探测“横折”这个形状。 卷积后得到3x3的Feature Map中,真正有用的就是数字为3的那个节点,其余数值对于这个任务而言都是无关的。 所以用3x3的Max pooling后,并没有对“横折”的探测产生影响。 试想在这里例子中如果不使用Max pooling,而让网络自己去学习。 网络也会去学习与Max pooling近似效果的权重。因为是近似效果,增加了更多的parameters的代价,却还不如直接进行Max pooling。

<img src="https://pic1.zhimg.com/50/v2-8e9d7ec0662e903e475bd93a64067554_hd.png" data-caption="" data-rawwidth="545" data-rawheight="345" class="origin_image zh-lightbox-thumb" width="545" data-original="https://pic1.zhimg.com/v2-8e9d7ec0662e903e475bd93a64067554_r.png">


Max pooling还有类似“选择句”的功能。假如有两个节点,其中第一个节点会在某些输入情况下最大,那么网络就只在这个节点上流通信息;而另一些输入又会让第二个节点的值最大,那么网络就转而走这个节点的分支。

但是Max pooling也有不好的地方。因为并非所有的抓取都像上图的极端例子。有些周边信息对某个概念是否存在的判定也有影响。 并且Max pooling是对所有的Feature Maps进行等价的操作。就好比用相同网孔的渔网打鱼,一定会有漏网之鱼。

全连接层

当抓取到足以用来识别图片的特征后,接下来的就是如何进行分类。 全连接层(也叫前馈层)就可以用来将最后的输出映射到线性可分的空间。 通常卷积网络的最后会将末端得到的长方体平摊(flatten)成一个长长的向量,并送入全连接层配合输出层进行分类。

卷积神经网络大致就是covolutional layer, pooling layer, ReLu layer, fully-connected layer的组合,例如下图所示的结构。

<img src="https://pic4.zhimg.com/50/v2-cf87890eb8f2358f23a1ac78eb764257_hd.png" data-caption="" data-rawwidth="748" data-rawheight="263" class="origin_image zh-lightbox-thumb" width="748" data-original="https://pic4.zhimg.com/v2-cf87890eb8f2358f23a1ac78eb764257_r.png">


[from]

这里也体现了深层神经网络或deep learning之所以称deep的一个原因:模型将特征抓取层和分类层合在了一起。 负责特征抓取的卷积层主要是用来学习“如何观察”。

下图简述了机器学习的发展,从最初的人工定义特征再放入分类器的方法,到让机器自己学习特征,再到如今尽量减少人为干涉的deep learning。

<img src="https://pic1.zhimg.com/50/v2-60e7c1e89c5aed5b828cbb24fc1e5a80_hd.png" data-caption="" data-rawwidth="566" data-rawheight="789" class="origin_image zh-lightbox-thumb" width="566" data-original="https://pic1.zhimg.com/v2-60e7c1e89c5aed5b828cbb24fc1e5a80_r.png">


[from]

结构发展

以上介绍了卷积神经网络的基本概念。 以下是几个比较有名的卷积神经网络结构,详细的请看CS231n

  • LeNet:第一个成功的卷积神经网络应用
  • AlexNet:类似LeNet,但更深更大。使用了层叠的卷积层来抓取特征(通常是一个卷积层马上一个max pooling层)
  • ZF Net:增加了中间卷积层的尺寸,让第一层的stride和filter size更小。
  • GoogLeNet:减少parameters数量,最后一层用max pooling层代替了全连接层,更重要的是Inception-v4模块的使用。
  • VGGNet:只使用3x3 卷积层和2x2 pooling层从头到尾堆叠。
  • ResNet:引入了跨层连接和batch normalization。
  • DenseNet:将跨层连接从头进行到尾。

总结一下:这些结构的发展趋势有:

  • 使用small filter size的卷积层和pooling
  • 去掉parameters过多的全连接层
  • Inception(稍后会对其中的细节进行说明)
  • 跳层连接

不变性的满足

接下来会谈谈我个人的,对于画面不变性是如何被卷积神经网络满足的想法。 同时结合不变性,对上面提到的结构发展的重要变动进行直觉上的解读。

需要明白的是为什么加入不变性可以提高网络表现。 并不是因为我们用了更炫酷的处理方式,而是加入了先验知识,无需从零开始用数据学习,节省了训练所需数据量。 思考表现提高的原因一定要从训练所需要的数据量切入。 提出满足新的不变性特点的神经网络是计算机视觉的一个主要研究方向。

平移不变性

可以说卷积神经网络最初引入局部连接和空间共享,就是为了满足平移不变性。

<img src="https://pic4.zhimg.com/50/v2-1aac56212d5d143a006d569318e3ee8b_hd.png" data-caption="" data-rawwidth="550" data-rawheight="136" class="origin_image zh-lightbox-thumb" width="550" data-original="https://pic4.zhimg.com/v2-1aac56212d5d143a006d569318e3ee8b_r.png">


因为空间共享,在不同位置的同一形状就可以被等价识别,所以不需要对每个位置都进行学习。

<img src="https://pic2.zhimg.com/50/v2-18c11c6f485e9f1bbc9a50eb3d248439_hd.png" data-caption="" data-rawwidth="411" data-rawheight="374" class="content_image" width="411">


旋转和视角不变性

个人觉得卷积神经网络克服这一不变性的主要手段还是靠大量的数据。 并没有明确加入“旋转和视角不变性”的先验特性。

<img src="https://pic2.zhimg.com/50/v2-0ce892f8b247f2b48a76cc57cbcba41d_hd.png" data-caption="" data-rawwidth="552" data-rawheight="250" class="origin_image zh-lightbox-thumb" width="552" data-original="https://pic2.zhimg.com/v2-0ce892f8b247f2b48a76cc57cbcba41d_r.png">


Deformable Convolutional Networks似乎是对此变性进行了进行增强。

尺寸不变性

与平移不变性不同,最初的卷积网络并没有明确照顾尺寸不变性这一特点。

我们知道filter的size是事先选择的,而不同的尺寸所寻找的形状(概念)范围不同。

从直观上思考,如果选择小范围,再一步步通过组合,仍然是可以得到大范围的形状。 如3x3尺寸的形状都是可以由2x2形状的图形组合而成。所以形状的尺寸不变性对卷积神经网络而言并不算问题。 这恐怕ZF Net让第一层的stride和filter size更小,VGGNet将所有filter size都设置成3x3仍可以得到优秀结果的一个原因。

但是,除了形状之外,很多概念的抓取通常需要考虑一个像素与周边更多像素之间的关系后得出。 也就是说5x5的filter也是有它的优点。 同时,小尺寸的堆叠需要很多个filters来共同完成,如果需要抓取的形状恰巧在5x5的范围,那么5x5会比3x3来的更有效率。 所以一次性使用多个不同filter size来抓取多个范围不同的概念是一种顺理成章的想法,而这个也就是Inception。 可以说Inception是为了尺寸不变性而引入的一个先验知识。

Inception

下图是Inception的结构,尽管也有不同的版本,但是其动机都是一样的:消除尺寸对于识别结果的影响,一次性使用多个不同filter size来抓取多个范围不同的概念,并让网络自己选择需要的特征。

你也一定注意到了蓝色的1x1卷积,撇开它,先看左边的这个结构。

输入(可以是被卷积完的长方体输出作为该层的输入)进来后,通常我们可以选择直接使用像素信息(1x1卷积)传递到下一层,可以选择3x3卷积,可以选择5x5卷积,还可以选择max pooling的方式downsample刚被卷积后的feature maps。 但在实际的网络设计中,究竟该如何选择需要大量的实验和经验的。 Inception就不用我们来选择,而是将4个选项给神经网络,让网络自己去选择最合适的解决方案。

接下来我们再看右边的这个结构,多了很多蓝色的1x1卷积。 这些1x1卷积的作用是为了让网络根据需要能够更灵活的控制数据的depth的。

<img src="https://pic2.zhimg.com/50/v2-9692631d087622f1b34c80055f13fac5_hd.png" data-caption="" data-rawwidth="983" data-rawheight="311" class="origin_image zh-lightbox-thumb" width="983" data-original="https://pic2.zhimg.com/v2-9692631d087622f1b34c80055f13fac5_r.png">


1x1卷积核

如果卷积的输出输入都只是一个平面,那么1x1卷积核并没有什么意义,它是完全不考虑像素与周边其他像素关系。 但卷积的输出输入是长方体,所以1x1卷积实际上是对每个像素点,在不同的channels上进行线性组合(信息整合),且保留了图片的原有平面结构,调控depth,从而完成升维或降维的功能。

如下图所示,如果选择2个filters的1x1卷积层,那么数据就从原本的depth 3 降到了2。若用4个filters,则起到了升维的作用。

这就是为什么上面Inception的4个选择中都混合一个1x1卷积,如右侧所展示的那样。 其中,绿色的1x1卷积本身就1x1卷积,所以不需要再用另一个1x1卷积。 而max pooling用来去掉卷积得到的Feature Map中的冗余信息,所以出现在1x1卷积之前,紧随刚被卷积后的feature maps。(由于没做过实验,不清楚调换顺序会有什么影响。)

<img src="https://pic1.zhimg.com/50/v2-59429b22ac90930c502736b33db0d8e0_hd.png" data-caption="" data-rawwidth="643" data-rawheight="517" class="origin_image zh-lightbox-thumb" width="643" data-original="https://pic1.zhimg.com/v2-59429b22ac90930c502736b33db0d8e0_r.png">


跳层连接

前馈神经网络也好,卷积神经网络也好,都是一层一层逐步变换的,不允许跳层组合。 但现实中是否有跳层组合的现象?

比如说我们在判断一个人的时候,很多时候我们并不是观察它的全部,或者给你的图片本身就是残缺的。 这时我们会靠单个五官,外加这个人的着装,再加他的身形来综合判断这个人,如下图所示。 这样,即便图片本身是残缺的也可以很好的判断它是什么。 这和前馈神经网络的先验知识不同,它允许不同层级之间的因素进行信息交互、综合判断。

残差网络就是拥有这种特点的神经网络。大家喜欢用identity mappings去解释为什么残差网络更优秀。 这里我只是提供了一个以先验知识的角度去理解的方式。 需要注意的是每一层并不会像我这里所展示的那样,会形成明确的五官层。 只是有这样的组合趋势,实际无法保证神经网络到底学到了什么内容。

<img src="https://pic4.zhimg.com/50/v2-40fb6ab7bf89ce43af1c52e673da65eb_hd.png" data-caption="" data-rawwidth="509" data-rawheight="507" class="origin_image zh-lightbox-thumb" width="509" data-original="https://pic4.zhimg.com/v2-40fb6ab7bf89ce43af1c52e673da65eb_r.png">


用下图举一个更易思考的例子。 图形1,2,3,4,5,6是第一层卷积层抓取到的概念。 图形7,8,9是第二层卷积层抓取到的概念。 图形7,8,9是由1,2,3,4,5,6的基础上组合而成的。

但当我们想要探测的图形10并不是单纯的靠图形7,8,9组成,而是第一个卷积层的图形6和第二个卷积层的8,9组成的话,不允许跨层连接的卷积网络不得不用更多的filter来保持第一层已经抓取到的图形信息。并且每次传递到下一层都需要学习那个用于保留前一层图形概念的filter的权重。 当层数变深后,会越来越难以保持,还需要max pooling将冗余信息去掉。

一个合理的做法就是直接将上一层所抓取的概念也跳层传递给下下一层,不用让其每次都重新学习。 就好比在编程时构建了不同规模的functions。 每个function我们都是保留,而不是重新再写一遍。提高了重用性。

同时,因为ResNet使用了跳层连接的方式。也不需要max pooling对保留低层信息时所产生的冗余信息进行去除。

<img src="https://pic3.zhimg.com/50/v2-87fc4b7449d751c59977c3a368ae6f7e_hd.png" data-caption="" data-rawwidth="484" data-rawheight="436" class="origin_image zh-lightbox-thumb" width="484" data-original="https://pic3.zhimg.com/v2-87fc4b7449d751c59977c3a368ae6f7e_r.png">


Inception中的第一个1x1的卷积通道也有类似的作用,但是1x1的卷积仍有权重需要学习。 并且Inception所使用的结合方式是concatenate的合并成一个更大的向量的方式,而ResNet的结合方式是sum。 两个结合方式各有优点。 concatenate当需要用不同的维度去组合成新观念的时候更有益。 而sum则更适用于并存的判断。比如既有油头发,又有胖身躯,同时穿着常年不洗的牛仔裤,三个不同层面的概念并存时,该人会被判定为程序员的情况。 又比如双向LSTM中正向和逆向序列抓取的结合常用相加的方式结合。在语音识别中,这表示既可以正向抓取某种特征,又可以反向抓取另一种特征。当两种特征同时存在时才会被识别成某个特定声音。

在下图的ResNet中,前一层的输入会跳过部分卷积层,将底层信息传递到高层。

<img src="https://pic4.zhimg.com/50/v2-d3fd09f011583932b832ea64f78233af_hd.png" data-caption="" data-rawwidth="317" data-rawheight="615" class="content_image" width="317">


在下图的DenseNet中,底层信息会被传递到所有的后续高层。

<img src="https://pic1.zhimg.com/50/v2-0bebba2947e5e968a93e6def0ae5d00c_hd.png" data-caption="" data-rawwidth="602" data-rawheight="389" class="origin_image zh-lightbox-thumb" width="602" data-original="https://pic1.zhimg.com/v2-0bebba2947e5e968a93e6def0ae5d00c_r.png">


后续

随着时间推移,各个ResNet,GoogLeNet等框架也都在原有的基础上进行了发展和改进。 但基本都是上文描述的概念的组合使用加上其他的tricks。

如下图所展示的,加入跳层连接的Inception-ResNet。

<img src="https://i-blog.csdnimg.cn/blog_migrate/69c572eb4436adc312b41b1a039c4f93.jpeg" data-caption="" data-rawwidth="1820" data-rawheight="1086" class="origin_image zh-lightbox-thumb" width="1820" data-original="https://pic3.zhimg.com/v2-389496d1436895dfe43199a0f54c35ca_r.jpg">


但对我而言,

真正重要的是这些技巧对于各种不变性的满足。



深度学习通俗易懂教程专栏超智能体 - 知乎专栏

阅读列表:

  1. 深层神经网络:深层学习为何要“Deep”(上)(由于下篇写的并不通俗,不推荐阅读,用公开课代替)
  2. 反向传播算法实例:未编写
  3. 深度学习总览:公开课:深层神经网络设计理念
  4. 深度学习入门误区:知乎Live(公开课涵盖了Live的内容,若觉得作者辛苦也可参加。算了,还是不要参加了!)
  5. Tensorflow :TensorFlow整体把握
  6. 前馈神经网络(1):前馈神经网络--代码LV1
  7. 前馈神经网络(2):前馈神经网络--代码LV2
  8. 前馈神经网络(3):前馈神经网络--代码LV3
  9. 循环神经网络(1)循环神经网络--介绍
  10. 循环神经网络(2)循环神经网络--实现LSTM
  11. 循环神经网络(3)循环神经网络--scan实现LSTM
  12. 循环神经网络(4)循环神经网络--双向GRU
  13. 卷积神经网络(1)卷积神经网络--介绍
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值