近几年随着功能强大的深度学习框架的出现,在深度学习模型中搭建卷积神经网络变得十分容易,甚至只需要一行代码就可以完成。
但是理解卷积,特别是对第一次接触卷积神经网络的人来说,经常会对诸如卷积核、滤波器、通道等概念和他们的堆叠架构感到困惑。然而卷积是强大且高度可扩展的概念,在本文中,我们将逐步分解卷积操作的原理,将他与标准的全连接网络联系起来,并且探索如何构建一个强大的视觉层次,使其成为高性能的图像特征提取器。
2 维卷积:操作
2 维卷积是一个相当简单的操作:从卷积核开始,这是一个小的权值矩阵。这个卷积核在 2 维输入数据上「滑动」,对当前输入的部分元素进行矩阵乘法,然后将结果汇为单个输出像素。
卷积核重复这个过程知道遍历了整张图片,将一个二维矩阵转换为另一个二维矩阵。输出特征实质上是在输入数据相同位置上的加权和(权值是卷积核本身的值)。
输入数据是否落入这个「大致相似区域」,直接决定了数据经过卷积核后的输出。这意味着卷积核的尺寸直接决定了生成新的特征时汇合了多少(或几个)输入特征。
这与全连接层完全相反。在上面的例子中,我们的输入特征为 55=25,输出数据为 33=9. 如果我们使用标准的全连接层,就会产生一个 25*9=225 个参数的权值矩阵,每个输出都是所有输入数据的加权求和。卷积操作允许我们只用 9 个参数来实现这个变换,每个输出特性不用「查看」每个输入特征,而是只是「查看」来自大致相同位置的输入特征。请注意这一点,因为这对我们后面的讨论至关重要。
一些常用的技术
在我们继续介绍卷积神经网络之前,介绍两种卷积层中常用的技术:Padding 和 Strides
Padding:如果你看到上面的动画,那么会注意到在卷积核滑动的过程中,边缘基本会被「裁剪」掉,将 55 特征矩阵转换为 33 的特征矩阵。边缘上的像素永远不在卷积核的中心,因为内核没有任何东西可以扩展到边缘之外。这并不理想,因为我们经常希望输出的尺寸等于输入。
Padding 做了一些非常机智的办法来解决这个问题:用额外的「假」像素(通常值为 0,因此经常使用的术语「零填充」)填充边缘。这样,在滑动时的卷积核可以允许原始边缘像素位于其中心,同时延伸到边缘之外的假像素,从而产生与输入相同大小的输出。
Striding:运行卷积层时,我们通常希望输出的尺寸是比输入更低。这在卷积神经网络中是常见的,在增加信道数量的同时空间尺寸减小。其中一种方法是使用池化层(例如,取每 2×2 网格的平均值/最大值将空间维度减半)。还有一种方法是使用 Striding:
Stride 的想法是改变卷积核的移动步长跳过一些像素。Stride 是 1 表示卷积核滑过每一个相距是 1 的像素,是最基本的单步滑动,作为标准卷积模式。Stride 是 2 表示卷积核的移动步长是 2,跳过相邻像素,图像缩小为原来的 1/2。Stride 是 3 表示卷积核的移动步长是 3,跳过 2 个相邻像素,图像缩小为原来的 1/3
越来越多的新网络结构,比如 ResNet,已经完全抛弃了池化层。当需要对图像进行缩小时会采用 Stride 方法。
多通道版本
当然,上图仅涉及具有单个输入通道的图像。实际上,大多数输入图像都是 3 通道的,通道数只会增加你的网络深度。通常会将图像的通道视作一个整体,强调其整体的一面而不关注各自的差异。
大部分时候,我们都处理 RBG 的三通道图像 (Credit: Andre Mouton)
这两个术语之间有着本质的区别:仅在 1 通道的情况下,滤波器和内核这两个术语等价,在一般情况下,它们是不同的。每个过滤器实际上是卷积核的集合,图层的每个输入通道都有一个卷积核,并且是唯一的。
卷积层中的每个滤波器都只输出一个通道,他们是这样实现的:
滤波器的每个卷积核在各自的输入通道上「滑动」,产生各自的计算结果。一些内核可能比其他内核具有更大的权重,以便比某些内核更强调某些输入通道(例如,滤波器的红色通道卷积核可能比其他通道的卷积核有更大的权重,因此,对红色通道特征的反应要强于其他通道)。
然后将每个通道处理的结果汇在一起形成一个通道。滤波器的卷积核各自产生一个对应通道的输出,最后整个滤波器产生一个总的输出通道。
最后一个术语:偏置。偏置在这里的作用是对每个输出滤波器增加偏置项以便产生最终输出通道。
其他数量滤波器的生成都和单滤波器相同:每个滤波器使用不同的卷积核集合和具有上述过程的标量偏差项来处理输入数据,最终产生一个输出通道。然后将它们连接在一起以产生总输出,其中输出通道的数量是过滤器的数量。在输出数据送入另一个卷积层之前,通常还要应用非线性激活函数。重复上述操作即可完成网络的搭建。
2 维卷积:直觉
卷积仍然是线性变换
即使有了卷积层的机制,仍然很难将它与标准的前馈网络联系起来,而且它仍然不能解释为什么卷积会扩展到图像数据处理领域,并且在这方面表现的很好。
假设我们有一个 4×4 的输入,我们需要将其转换成 2×2 的阵列。如果我们使用前馈网络,我们会先将 4×4 的输入转换成长度为 16 的向量,然后输入一个拥有 16 个输入和 4 个输出的密集连接层。可以为这一层想象一个权值矩阵 W :
总而言之,有 64 个参数。
尽管卷积核运算一开始看起来很奇怪,但它仍然是一个线性变换,有一个等价的变换矩阵。如果我们将大小为 3 的核 K 应用于变换后的 4×4 输入,来得到 2×2 的输出,等价的变换矩阵将是:
这里有 9 个参数
(注意:虽然上面的矩阵是一个等价的变换矩阵,但实际操作通常是作为一个非常不同的矩阵乘法来实现的 [2])
卷积,作为一个整体,仍然是一个线性变换,但同时,这也是一种与众不同的变换。一个有 64 个元素的矩阵,只有 9 个参数被重复使用。每个输出节点只能看到特定输入的数量(核内部的输入)。与其他输入没有任何交互,因为权值被设置为 0。
将卷积操作看作是权值矩阵的先验是很有用的。在这篇文章中,我预先定义了网络参数。例如,当你使用预先训练的模型做图像分类时,前提是使用预先训练的网络参数,作为密集链接层的一个特征提取器。
从这层意义上说,有一个直觉就是为什么两个都很有效呢(与他们的替代者比较)。迁移学习的效率比随机初始化高出多个数量级,因为你只需要优化最终全连接层的参数,这意味着您可以拥有出色的性能,每个类只有几十个图像。
这里,你不需要优化所有 64 个参数,因为我们将其中的大部分设置为 0(而且始终保持这个值),剩余的转化成共享参数,这将导致实际上只需要优化 9 个参数。这个效率很重要,当从 MNIST 的 784 个输入转换成实际的 224×224×3 个图像时,将会有 150000 个输入。密集层视图将输入减半为 75000 个,这仍然需要 100 亿个参数。相比而言,ResNet-50 总共只有 2 千 500 万个参数。
所以,将一些参数固定为 0,邦定参数提高效率,但与迁移学习不同,在迁移学习中,我们知道先验是不是好的,因为它依赖于大量的图像,我们如何知道这个的好坏呢?
答案就在特征组合中,前面的参数是要学习的参数。
局部性
在这片文章的开始,我们讨论了以下问题:
卷积核只从一个小的局部区域组合像素来形成输出。也就是说,输出特性只从一个小的局部区域「看到」输入特性。
卷积核被应用于整个图像,以产生输出矩阵。
所以随着反向传播从网络的分类节点一路过来,卷积核拥有一个有趣的任务,从局部输入中学习权值,生成特征。此外,因为卷积核本身被应用于整个图像,卷积核学习的特征必须足够通用,可以来自于图像的任何部分。
如果这是任何其他种类的数据,例如,APP 安装的分类数据,这将会是一场灾难,因为你的应用程序安装数量和应用类型是相邻的,并不意味着它们有任何与应用安装日期和使用时间一样常见的「本地的、共享的特性」。当然,它们可能有一个可被发现的潜在高层次的特征(例如。人们最需要的是哪些应用程序),但这并没有给我们足够的理由相信前两个的参数和后两个的参数完全相同。这四种可能是任意的(一致的)顺序,并且仍然有效!
然而,像素总是以一致的顺序出现,而且附近的像素互相影响。例如,如果某像素附近所有像素都是红色的,那么该像素极有可能也是红色的。如果有偏差,这是一个有趣的反常现象,可以转化成一个特征,所有这些偏差可以通过与周围像素的比较检测出来。
这个想法实际上是很多早期的计算机视觉特征提取方法的基础。例如,对于边缘检测,你可以使用 Sobel 边缘检测滤波器,这是一个具有固定参数的核,运算过程和标准的单通道卷积一样:
对于没有边缘的阵列(例如天空背景),大部分像素是一样的值,所以卷积核在这些点输出为 0。对于有垂直边缘的阵列,边缘左右两侧的像素是不同的,卷积核的计算结果也是非零的,从而揭示边缘。在检测局部范围内异常时,卷积核一次只作用于 3 × 3 的阵列,但是当应用到整个图像时,也足以在全局范围内检测到来自于在图像的任何位置的某个特定的特征,!
所以我们在深度学习中所做的关键区别是问这个问题:有用的核能被学习吗?对于以原始像素为基础的初始层,我们可以合理地期望具有相当低水平特征的特征检测器,如边、线等。
深度学习研究有一个专注于神经网络可解释性的完整分支。这一分支最强大的工具之一是使用优化方法可视化特征 [3]。核心思想很简单:优化图像(通常是使用随机噪声初始化)来激活滤波器,使其尽可能强壮。这确实很直观:如果经过优化的图像完全被边缘填充,这就是过滤器本身所寻找并被激活的强有力的证据。使用这个,我们可以窥视到学习的过滤器,结果是惊人的:
来自 GoogLeNet[3] 第一个卷积层的 3 个不同通道的特征可视化,注意,即便它们检测到不同的边缘类型时,它们仍然是很低级的边缘检测器。
这里需要注意的一个重要的事情是经过卷积的图像仍然是图像。来自图像左上角的小阵列像素输出依然位于左上角。所以你可以在另一个上面运行另一个卷积层(比如左边的两个)来提取更深层的特征,这我们可以想象到。
然而,无论我们的特征探测器能检测到多深,没有任何进一步的改变,它们仍然只能在非常小的图像上运行。无论你的探测器有多深,你都无法从 3×3 阵列中检测到人脸。这就是感受域的概念。
感受域
任何 CNN 架构的一个基本的设计选择是输入的大小从开始到网络的末端变得越来越小,而通道的数量越来越深。如之前所述,这个经常是通过步长或池化层完成的。Locality 决定了输出层看到的前一层的输入。感受域决定了从输出的角度看到的整个网络的原始输入区域。
条纹卷积的概念是我们只处理一个固定的距离,而忽略中间的那些。从不同的视角,我们只保持固定距离的输出,而移去剩余部分 [1]。
然后我们对输出应用非线性,然后根据通常情况,在上面叠加另一个新的卷积层。这就是有趣的地方。即使我们将有相同大小和相同局部区域的核(3×3),应用到条纹卷积的输出,核将会拥有更大的感受域:
这是因为条纹层的输出仍然代表相同图像。它不像调整大小那样裁剪,唯一的问题是,输出中的每个像素都是一个较大区域(其他像素被丢弃)的「代表性」,从原始输入的相同的粗糙位置。因此,当下一层的核在输出上运行时,它实际运行于从更大的区域收集的像素上。
(注意:如果你熟悉扩张卷积,注意上面的不是扩张卷积。两个都是增加感受域的方法,扩张卷积是一个单独层,而这是发生在一个正规卷积上,之后是条纹卷积,中间帧是非线性)
对每个主要的卷积块集合的通道进行可视化,显示复杂性的逐步增加 [3]
这个感受域的扩展允许卷积层将低层次的特性(线,边)与更高层次的特征(曲线,纹理)组合,就像我们在 mixed3a 层中看到的那样。
紧接着是池化/ 跨越层 , 网络继续为更高级别的特性(部件、模式)创建检测器。如我们在 mixed4a 所看到的。
网络中,图像尺寸的重复减小,导致在卷积的第五个块中,其输入大小仅 7×7,与 224×224 的输入相比。从这点来看,每个单独像素代表了 32×32 像素阵列,这是相当大的。
与前面的层相比,对前面的层来说,一个激活意味着检测一个边界,而这里,7×7 上的激活就是一个高级的特征,例如鸟类。
整个网络从少量的滤波器(GoogLeNet 有 64 个),只能检测低级的特征,发展到拥有大量滤波器(在最终的卷积网络中有 1024 个),每个滤波器用于查找特定的高级特征。之后是池化层,将每个 7×7 阵列精简成 1 个像素,每个通道都是一个拥有一个与整个图像对应的感受域的特征检测器。
与前向传播网络所完成的工作相比,这里的输出令人惊讶。一个标准前向传播网络从图像的像素集合中生成抽象的特征向量,需要大量难以处理的数据进行训练。
卷积神经网络,with the priors imposed on it, 通过学习低级别的特征检测器开始,它的感受域逐层扩展,学习将那些低级的特征逐渐与高层的特征融合;不是每个单个像素的抽象结合,而是强大的视觉层次的概念。
通过检测第级别的特征,并使用它们检测高级别特征,随着视觉层次的发展,最终能够检测整个视觉概念,例如人脸、鸟类、树木等,这就是为什么它们如此强大,但却能有效地利用图像数据。
关于对抗攻击的最后说明
有了视觉层次卷积神经网络的构建,我们可以很合理地假设他们的视觉系统与人类相似。他们在处理真实世界的图像时表现很棒,但是它们在某些方面也失败了,这强烈地表明他们的视觉系统和人类的并不完全相似。最主要的问题:对抗样本 [4],这些样本被做了特别修改导致模型被愚弄。
对人类来说,两张图片明显都是熊猫,但对模型来说,并不是这样。[4]
如果人类能够注意到那些导致模型失败的被篡改的例子,那么对抗样本就不是问题了。问题是,这些模型容易受到样本的攻击,这些样本只被稍微修改过,而且显然不会欺骗任何人类。这为模型打开了一扇门,很小的失败,对于从自动驾驶汽车到医疗保健的广泛应用来说,是相当危险的。
对抗攻击的鲁棒性是目前高度活跃的研究领域,许多论文、甚至竞赛和解决方案的课题肯定会改善 CNN 的架构,使其变得更安全、更可靠。
结论
卷积神经网络是允许计算机视觉从简单的应用程序扩展到为复杂的产品和服务提供动力的模型,从你的照片库中的人脸检测到做出更好的医学诊断。它可能会是计算机视觉向前发展的关键方法,或者一些新的突破可能就在眼前。
无论如何,有一件事是肯定的:它们都是令人惊叹的东西,是当今许多创新应用的核心,而且最值得深入理解。
原文发布时间为:2018-07-18
本文来自云栖社区合作伙伴“机器学习算法与Python学习”,了解相关信息可以关注“机器学习算法与Python学习”