深度学习之所以让我兴奋有下面两个原因,我想你们也是这么想的:
第一,计算机视觉的高速发展标志着新型应用产生的可能人们对于计算机视觉的研究是如此富有想象力和创造力,由此衍生出新的神经网络结构与算法,这实际上启发人们去创造出计算机视觉与其他领域的交叉成果。在参数如此大量的情况下,难以获得足够的数据来防止神经网络发生过拟合和竞争需求,要处理包含 30 亿参数的神经网络,巨大的内存需求让人不太能接受。
但对于计算机视觉应用来说,你肯定不想它只处理小图片,你希望它同时也要能处理大图。为此,你需要进行卷积计算,它是卷积神经网络中非常重要的一块。
看一个例子,这是一个 6×6 的灰度图像。因为是灰度图像,所以它是 6×6×1 的矩阵,它被称为过滤器。我要构造一个 3×3 的过滤器,像这样[1 0 −1; 1 0 −1; 1 0 −1]。在论文它有时候会被称为核。 然后将该矩阵每个元素相加得到最左上角的元素,即3 + 1 + 2 + 0 + 0 + 0 + (−1) + (−8) + (−2) = −5。 继续做同样的元素乘法,然后加起来,所以是 0 × 1 + 5 × 1 + 7 × 1 + 1 × 0 + 8 × 0 + 2 × 0 + 2 × (−1) + 9 × (−1) + 5 × (−1) = −4。
因此 6×6 矩阵和 3×3 矩阵进行卷积运算得到 4×4 矩阵。这些图片和过滤器是不同维度的矩阵,但左边矩阵容易被理解为一张图片,中间的这个被理解为过滤器,右边的图片我们可以理解为另一张图片。这个就是垂直边缘检测器,下一页中你就会明白。 不同的编程语言有不同的函数,而不是用“∗”来表示卷积。果在 tensorflow 下,这个函数叫 tf.conv2d。将会看到 Keras 这个框架,在这个框架下用 Conv2D 实现卷积运算。 卷积运算提供了一个方便的方法来发现图像中的垂直边缘。
总而言之,通过使用不同的过滤器,你可以找出垂直的或是水平的边缘。但事实上,对于这个 3×3 的过滤器来说,我们使用了其中的一种数字组合。
[1 0 −1; 2 0 −2; 1 0 −1],叫做 Sobel 的过滤器,它的优点在于增加了中间一行元素的权重,这使得结果的鲁棒性会更高一些。[3 0 −3;10 0 −10;3 0 −3 ],这叫做 Scharr 过滤器,它有着和之前完全不同的特性,实际上也是一种垂直边缘检测,如果你将其翻转 90 度,你就能得到对应水平边缘检测。 这种过滤器对于数据的捕捉能力甚至可以胜过任何之前这些手写的过滤器。相比这种单纯的垂直边缘和水平边缘,它可以检测出45°或70°或73°,甚至是任何角度的边缘。所以将矩阵的所有数字都设置为参数,通过数据反馈,让神经网络自动去学习它们,我们会发现神经网络可以学习一些低级的特征。
所以这种将这 9 个数字当成参数的思想,已经成为计算机视觉中最为有效的思想之一。也就是下个星期,我们将详细去探讨如何使用反向传播去让神经网络学习这 9 个数字。
如果我们有一个𝑛 × 𝑛的图像,用𝑓 × 𝑓的过滤器做卷积,那么输出的维度就是(𝑛 − 𝑓 + 1) × (𝑛 − 𝑓 + 1)。
这样的话会有两个缺点,第一个缺点是每次做卷积操作,你的图像就会缩小。第二个缺点是,那些在角落或者边缘区域的像素点在输出中采用较少,意味着你丢掉了图像边缘位置的许多信息。
为了解决这些问题,你可以在卷积操作之前填充这幅图像。在这个案例中,你可以沿着图像边缘再填充一层像素。如果你这样操作了,那么 6×6 的图像就被你填充成了一个 8×8 的图像。如果你用 3×3 的图像对这个 8×8 的图像卷积,你得到的输出就不是 4×4 的,而是 6×6的图像。这样一来,丢失信息或者更准确来说角落或图像边缘的信息发挥的作用较小的这一缺点就被削弱了。
至于选择填充多少像素,通常有两个选择,分别叫做 Valid 卷积和 Same 卷积。 Valid 卷积意味着不填充。 另一个经常被用到的填充方法叫做 Same 卷积,那意味你填充后,你的输出大小和输入大小是一样的。根据这个公式𝑛 − 𝑓 + 1,当你填充𝑝个像素点,那么𝑝 = (𝑓 − 1)/2。
你已经看到如何使用 padding 卷积,为了指定卷积操作中的 padding,你可以指定𝑝的值。也可以使用 Valid 卷积,也就是𝑝 = 0。也可使用 Same 卷积填充像素,使你的输出和输入大小相同。
我们把步幅设置成了2。你还和之前一样取左上方的 3×3 区域的元素的乘积,再加起来,最后结果为 91。 如果你用一个𝑓 × 𝑓的过滤器卷积一个𝑛 × 𝑛的图像,你的 padding 为𝑝,步幅为𝑠,在这个例子中𝑠 = 2,你会得到一个输出,因为现在你不是一次移动一个步子,而是一次移动𝑠个步子,输出于是变为[(𝑛+2𝑝−𝑓)/𝑠 + 1] × [(𝑛+2𝑝−𝑓)/𝑠 +1]。
现在只剩下最后的一个细节了,如果商不是一个整数怎么办?
这个 3×3×3 的过滤器有 27 个数,27 个参数就是 3 的立方。依次取这 27 个数,然后乘以相应的红绿蓝通道中的数字。后把这些数都加起来,就得到了输出的第一个数字。 如果你想检测图像红色通道的边缘,那么你可以将第一个过滤器设为[1 0 −1 ;1 0 −1; 1 0 −1],和之前一样,而绿色通道全为 0,[0 0 0 ;0 0 0 ;0 0 0],蓝色也全为 0。
或者如果你不关心垂直边界在哪个颜色通道里,那么你可以用一个这样的过滤器,[1 0 −1 1 0 −1 1 0 −1],[1 0 −1 1 0 −1 1 0 −1],[1 0 −1 1 0 −1 1 0 −1],所有三个通道都是这样。
如果我们不仅仅想要检测垂直边缘怎么办?如果我们同时检测垂直边缘和水平边缘,还有 45°倾斜的边缘,还有 70°倾斜的边缘怎么做?换句话说,如果你想同时用多个过滤器怎么办? (第一个)这可能是一个垂直边界检测器或者是学习检测其他的特征。第二个过滤器可以用橘色来表示,它可以是一个水平边缘检测器。 所以把这两个输出堆叠在一起,这样你就都得到了一个 4×4×2 的输出立方体。
我们总结一下维度,如果你有一个𝑛 × 𝑛 × 𝑛𝑐(通道数)的输入图像,然后卷积上一个𝑓 × 𝑓 × 𝑛𝑐,后你就得到了(𝑛 − 𝑓 + 1)× (𝑛 − 𝑓 + 1) × 𝑛𝑐′,这里𝑛𝑐′其实就是下一层的通道数,它就是你用的过滤器的个数,你用了不同的步幅或者padding,那么这个𝑛 − 𝑓 + 1数值会变化。
这就是𝑎[0]到𝑎[1]的演变过程,首先执行线性函数,然后所有元素相乘做卷积,具体做法是运用线性函数再加上偏差,然后应用激活函数 ReLU。这样就通过神经网络的一层把一个6×6×3 的维度𝑎[0]演化为一个4×4×2 维度的𝑎[1],这就是卷积神经网络的一层。
假设你有 10 个过滤器,而不是 2 个,神经网络的一层是 3×3×3,那么,这一层有多少个参数呢?每个过滤器有 27 个参数,也就是 27 个数。然后加上一个偏差,用参数𝑏表示,现在参数增加到 28 个。而现在我们有 10 个,加在一起 是 28×10,也就是 280 个参数。 请注意一点,不论输入图片有多大,1000×1000 也好,5000×5000 也好,参数始终都是280 个。用这 10 个过滤器来提取特征,如垂直边缘,水平边缘和其它特征。即使这些图片很大,参数却很少,这就是卷积神经网络的一个特征,叫作“避免过拟合”。
用𝑓[𝑙]表示过滤器大小,我们说过过滤器大小为𝑓 × 𝑓,上标[𝑙]表示𝑙层中过滤器大小为𝑓 × f。用𝑝[𝑙]来标记 padding 的数量,用𝑠[𝑙]标记步幅。
这一层的输入会是某个维度的数据,即𝑛[𝑙−1] × 𝑛[𝑙−1] × 𝑛𝑐[𝑙−1],因为它是上一层的激活值。所用图片的高度和宽度都一样,但它们也有可能不同,即𝑛𝐻[𝑙−1] × 𝑛𝑊[𝑙−1] × 𝑛𝑐[𝑙−1]。𝑙层的输入就是上一层的输出,因此上标要用[𝑙 − 1]。神经网络这一层中会有输出,它本身会输出图像。其大小为𝑛𝐻[𝑙] × 𝑛𝑊[𝑙] × 𝑛𝑐[𝑙],这就是输出图像的大小。 这就是由𝑛𝐻[𝑙-1] 推导𝑛𝐻[𝑙] 以及𝑛W[𝑙-1] 推导𝑛w[𝑙] 。
输出通道数量就是输入通道数量,所以过滤器维度等于𝑓[𝑙] × 𝑓[𝑙] × 𝑛𝑐[𝑙−1]。
应用偏差和非线性函数之后,这一层的输出等于它的激活值𝑎[𝑙],𝑎[𝑙]是一个三维体,即𝑛𝐻[𝑙] × 𝑛𝑊[𝑙] × 𝑛𝑐[𝑙]。该如何确定权重参数,即参数 W 呢?过滤器的维度已知,为𝑓[𝑙] × 𝑓[𝑙]× 𝑛𝑐[𝑙−1],这只是一个过滤器的度,𝑓[𝑙] × 𝑓[𝑙]× 𝑛𝑐[𝑙−1] × 𝑛𝑐[𝑙],损失数量 L 就是𝑙层中过滤器的个数 偏差在代码中表示为一个 1×1×1× 𝑛𝑐[𝑙]的四维向量或四维张量。
而这节课你要掌握的一点是,随着神经网络计算深度不断加深,通常开始时的图像也要更大一些,初始值为 39×39,高度和宽度会在一段时间内保持一致,然后随着网络深度的加深而逐渐减小,从 39 到 37,再到 17,最后到 7。而通道数量在增加,从 3 到 10,再到 20,最后到 40。
一个典型的卷积神经网络通常有三层,一个是卷积层,我们常常用 Conv 来标注。上一个例子,我用的就是 CONV。还有两种常见类型的层,我们留在后两节课讲。一个是池化层,我们称之为 POOL。最后一个是全连接层,用 FC 表示。虽然仅用卷积层也有可能构建出很好的神经网络,但大部分神经望楼架构师依然会添加池化层和全连接层。幸运的是,池化层和全连接层比卷积层更容易设计。
假如输入是一个 4×4 矩阵,用到的池化类型是最大池化(max pooling)。执行最大池化的树池是一个 2×2 矩阵。 这就像是应用了一个规模为 2 的过滤器,因为我们选用的是 2×2 区域,步幅是 2,这些就是最大池化的超参数。
数字大意味着可能探测到了某些特定的特征,最大化操作的功能就是只要在任何一个象限内提取到某个特征,它都会保留在最大化的池化输出里。所以最大化运算的实际作用就是,如果在过滤器中提取到某个特征,那么保留其最大值。如果没有提取到这个特征,可能在右上象限中不存在这个特征,那么其中的最大值也还是很小,这就是最大池化的直观理解。
其中一个有意思的特点就是,它有一组超参数,但并没有参数需要学习。它的过滤器参数为 3×3,即𝑓 = 3,步幅为 1,𝑠 = 1,输出矩阵是 3×3。之前讲的计算卷积层输出大小的公式同样适用于最大池化,即(𝑛+2𝑝−𝑓)/ 𝑠 + 1。 如果输入是三维的,那么输出也是三维的。输入是 5×5×2,那么输出是 3×3×2。
𝑛𝑐个通道中每个通道都单独执行最大池化计算,以上就是最大池化算法。
另外还有一种类型的池化,平均池化,它不太常用。 总结一下,池化的超级参数包括过滤器大小𝑓和步幅𝑠,池化过程中没有需要学习的参数。执行反向传播时,反向传播没有参数适用于最大池化。
32×32×3 的 RGB 图片中含有某个数字,比如 7,你想识别它是从 0-9 这 10 个数字中的哪一个,我们构建一个神经网络来实现这个功能。
输入是 32×32×3 的矩阵,假设第一层使用过滤器大小为 5×5,步幅是 1,padding 是 0,过滤器个数为 6,那么输出为28×28×6。将这层标记为 CONV1,它用了 6 个过滤器,增加了偏差,应用了非线性函数,可能是 ReLU 非线性函数,最后输出 CONV1 的结果。
然后构建一个池化层,这里我选择用最大池化,参数𝑓 = 2,𝑠 = 2,因为 padding 为 0,因此,28×28 变成了 14×14, 一个卷积层和一个池化层一起作为一层,这就是神经网络的 Layer1。
我们再为它构建一个卷积层,过滤器大小为 5×5,步幅为 1,这次我们用 10 个过滤器,最后输出一个 10×10×10 的矩阵,标记为 CONV2。 然后做最大池化,超参数𝑓 = 2,𝑠 = 2。你大概可以猜出结果,𝑓 = 2,𝑠 = 2,高度和宽度会减半,最后输出为5×5×10,标记为POOL2,这就是神经网络的第二个卷积层,即Layer2。
5×5×16 矩阵包含 400 个元素,现在将 POOL2 平整化为一个大小为 400 的一维向量。我们可以把平整化结果想象成这样的一个神经元集合,然后利用这 400 个单元构建下一层。下一层含有 120 个单元,这就是我们第一个全连接层,标记为 FC3。这是一个标准的神经网络。它的权重矩阵为𝑊[3],维度为 120×400。最后输出 120 个维度。 然后我们对这个 120 个单元再添加一个全连接层,这层更小,假设它含有 84 个单元,标记为 FC4。 最后,用这 84 个单元填充一个 softmax 单元。如果我们想通过手写数字识别来识别手写 0-9 这 10 个数字,这个 softmax 就会有 10 个输出。
现在,我想指出的是,随着神经网络深度的加深,高度𝑛𝐻和宽度𝑛𝑊通常都会减少,前面我就提到过,从 32×32 到 28×28,到 14×14,到 10×10,再到 5×5。所以随着层数增加,高度和宽度都会减小,而通道数量会增加,从 3 到 6 到 16 不断增加,然后得到一个全连接层。 在神经网络中,另一种常见模式就是一个或多个卷积后面跟随一个池化层,然后一个或多个卷积层后面再跟一个池化层,然后是几个全连接层,最后是一个 softmax。这是神经网络的另一种常见模式。 有几点要注意,第一,池化层和最大池化层没有参数;第二卷积层的参数相对较少,其实许多参数都存在于神经网络的全连接层。观察可发现,随着神经网络的加深,激活值尺寸会逐渐变小,如果激活值尺寸下降太快,也会影响神经网络性能。
一个卷积神经网络包括卷积层、池化层和全连接层。据我的经验,找到整合基本构造模块最好方法就是大量阅读别人的案例。下周我会演示一些整合基本模块,成功构建高效神经网络的具体案例。
卷积层的两个主要优势在于参数共享和稀疏连接,
假设有一张 32×32×3 维度的图片,假设用了 6 个大小为 5×5 的过滤器,输出维度为 28×28×6。32×32×3=3072,28×28×6=4704。我们构建一个神经网络,其中一层含有 3072 个单元,下一层含有 4074 个单元,两层中的每个神经元彼此相连,然后计算权重矩阵,它等于 4074×3072≈1400 万,所以要训练的参数很多。我们看看这个卷积层的参数数量,每个过滤器都是 5×5,一个过滤器有 25 个参数,再加上偏差参数,那么每个过滤器就有 26 个参数,一共有 6 个过滤器,所以参数共计 156 个,参数数量还是很少。
卷积网络映射这么少参数有两个原因: 一是参数共享。观察发现,特征检测如垂直边缘检测如果适用于图片的某个区域,那么它也可能适用于图片的其他区域。 第二个方法是使用稀疏连接。这个 0 是通过 3×3 的卷积计算得到的,它只依赖于这个 3×3 的输入的单元格。而且其它像素值都不会对输出产生任影响,这就是稀疏连接的概念。 神经网络可以通过这两种机制减少参数,以便我们用更小的训练集来训练它,从而预防过度拟合。你们也可能听过,卷积神经网络善于捕捉平移不变。因为神经网络的卷积结构使得即使移动几个像素,这张图片依然具有非常相似的特征。 就是卷积或卷积网络在计算机视觉任务中表现良好的原因。 我们选定了一个卷积神经网络,输入图片,增加卷积层和池化层,然后添加全连接层,最后输出一个 softmax,即𝑦^。卷积层和全连接层有不同的参数𝑤和偏差𝑏,我们可以用任何参数集合来定义代价函数。并随机初始化其参数𝑤和𝑏,训练神经网络,你要做的就是使用梯度下降法,或其它算法。过上述操作你可以构建一个高效的猫咪检测器或其它检测器。