卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现

1 边缘检测

1.1 垂直检测

        让我们举个例子,给了这样一张图片,让电脑去搞清楚这张照片里有什么物体,你可能做的第一件事是检测图片中的垂直边缘。比如说,在这张图片中的栏杆就对应垂直线,与此同时,这些行人的轮廓线某种程度上也是垂线,这些线是垂直边缘检测器的输出。同样,你可能也想检测水平边缘,比如说这些栏杆就是很明显的水平线,它们也能被检测到。所以如何在图像中检测这些边缘?

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第1张图片

        看一个垂直检测的例子,这是一个 6×6 的灰度图像。因为是灰度图像,所以它是 6×6×1 的矩阵,而不是 6×6×3 的,因为没有 RGB 三通道。为了检测图像中的垂直边缘,你可以构造一个 3×3 矩阵。在共用习惯中,在卷积神经网络的术语中,它被称为过滤器。我要构造一个 3×3 的过滤器,在论文它有时候会被称为核,而不是过滤器。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第2张图片

      如果在 tensorflow深度学习框架中 ,用tf.conv2d这个函数来实现卷积操作。为什么这个过滤器可以做垂直边缘检测呢?让我们来看另外一个例子。为了讲清楚,我会用一个简单的例子。这是一个简单的 6×6 图像,左边的一半是 10,右边一般是 0。如果你把它当成一个图片,左边那部分看起来是白色的,像素值 10 是比较亮的像素值,右边像素值比较暗,我使用灰色来表示 0,尽管它也可以被画成黑的。图片里有一个特别明显的垂直边缘在图像中间,这条垂直线是从黑到白的过渡线,或者从白色到深色。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第3张图片

        如果把最右边的矩阵当成图像,它是这个样子。在中间有段亮一点的区域,对应检查到这个 6×6 图像中间的垂直边缘。这里的维数似乎有点不正确,检测到的边缘太粗了。因为在这个例子中,图片太小了。如果你用一个 1000×1000 的图像,而不是 6×6 的图片,你会发现其会很好地检测出图像中的垂直边缘。在这个例子中,在输出图像中间的亮处,表示在图像中间有一个特别明显的垂直边缘。从垂直边缘检测中可以得到的启发是:卷积运算提供了一个方便的方法来发现图像中的垂直边缘。

1.2 更多边缘检测

        一个垂直边缘过滤器是一个 3×3 的区域,它的左边相对较亮,而右边相对较暗。相似的,右边这个水平边缘过滤器也是一个 3×3 的区域,它的上边相对较亮,而下方相对较暗。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第4张图片

       总而言之,通过使用不同的过滤器,你可以找出垂直的或是水平的边缘。但事实上,对于这个 3×3 的过滤器来说,我们使用了其中的一种数字组合。随着深度学习的发展,我们学习的其中一件事就是当你真正想去检测出复杂图像的边缘,你不一定要去使用那些研究者们所选择的这九个数字,但你可以从中获益匪浅。把这矩阵中的 9 个数字当成 9 个参数,并且在之后你可以学习使用反向传播算法,其目标就是去理解这9 个参数。使它可以检测出 45°或 70°或 73°,甚至是任何角度的边缘。所以将矩阵的所有数字都设置为参数,通过数据反馈,让神经网络自动去学习它们。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第5张图片

2 padding

        为了构建卷积神经网络,你需要学会使用的一个基本的卷积操作就是 padding,让我们来看看它是如何工作的。在之前,如果你用一个 3×3 的过滤器卷积一个 6×6 的图像,你最后会得到一个 4×4 的输出。那是因为你的 3×3 过滤器在 6×6 矩阵中,只可能有 4×4 种可能的位置。这如果我们有一个 n×n 的图像,用 f×f 的过滤器做卷积,那么输出的维度就是(n-f+1)×(n-f+1)。在这个例子里是 6-3+1=4,因此得到了一个 4×4 的输出。这样的话会有两个缺点,第一个缺点是每次做卷积操作,你的图像就会缩小,你可能做了几次之后,你的图像就会变得很小了,可能会缩小到只有 1×1 的大小。你可不想让你的图像在每次识别边缘或其他特征时都缩小,这就是第一个缺点。第二个缺点,如果你注意角落边缘的像素,这个像素点只被一个输出所触碰或者使用,因为它位于这个 3×3 的区域的一角。但如果是在中间的像素点,就会有许多 3×3 的区域与之重叠。所以那些在角落或者边缘区域的像素点在输出中采用较少,意味着你丢掉了图像边缘位置的许多信息。为了解决这两个问题,我们使用padding操作。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第6张图片

        你可以在卷积操作之前填充这幅图像。在这个案例中,你可以沿着图像边缘再填充一层像素。那么 6×6 的图像就被你填充成了一个 8×8的图像。如果你用 3×3 的图像对这个 8×8 的图像卷积,你得到的输出就不是 4×4 的,而是 6×6 的图像。习惯上,用 0 去填充,如果 p 是填充的数量,在里p=1,因为我们在周围都填充了一个像素点,输出也就变成了(n+2p-f+1)×(n+2p-f+1),所以就变成了(6+2×1-3+1)×(6+2×1-3+1)= 6×6,和输入的图像一样大。这个涂绿的像素点(左边矩阵)影响了输出中的这些格子(右边矩阵)。这样一来,丢失信息或者更准确来说角落或图像边缘的信息发挥的作用较小的这一缺点就被削弱了。刚才我们已经展示过用一个像素点来填充边缘,如果你想的话,也可以填充两个像素点。至于选择填充多少像素,通常有两个选择,分别叫做 Valid 卷积和 Same 卷积。Valid 卷积意味着不填充, Same 卷积意味你填充后,你的输出大小和输入大小是一样的。根据这个公式 n-f+1,当你填充 p 个像素点,n 就变成了 n+2p,最后公式变为 n+2p-f+1。如果你想让 n+2p-f+1=n 的话,使得输出和输入大小相等,如果你用这个等式求解 p,那么 p=(f-1)/2。所以当 f 是一个奇数的时候,只要选择相应的填充尺寸,你就能确保得到和输入相同尺寸的输出。

3   卷积步长(Strided convolutions)

        卷积中的步幅是另一个构建卷积神经网络的基本操作,让我向你展示一个例子。如果你想用 3×3 的过滤器卷积这个 7×7 的图像,和之前不同的是,我们把步幅设置成了 2。你还和之前一样取左上方的 3×3 区域的元素的乘积,再加起来,最后结果为 91。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第7张图片

        所以在这个例子中,我们用 3×3 的矩阵卷积一个 7×7 的矩阵,得到一个 3×3 的输出。输入和输出的维度是由下面的公式决定的。如果你用一个 f×f 的过滤器卷积一个 n×n 的图像,你的 padding 为 p,步幅为 s,在这个例子中 s=2,你会得到一个输出,因为现在你不是一次移动一个步子,而是一次移动 s 个步子,输出于是变为在我们的这个例子里,n=7,p=0,f=3,s=2,即 3×3 的输出。现在只剩下最后的一个细节了,如果商不是一个整数怎么办?在这种情况下,我们向下
取整。

4 三维卷积

        你已经知道如何对二维图像做卷积了,现在看看如何执行卷积不仅仅在二维图像上,而是三维立体上。我们从一个例子开始,假如说你不仅想检测灰度图像的特征,也想检测 RGB 彩色图像的特征。彩色图像如果是 6×6×3,这里的 3 指的是三个颜色通道,你可以把它想象成三个6×6 图像的堆叠。为了检测图像的边缘或者其他的特征,不是把它跟原来的 3×3 的过滤器做卷积,而是跟一个三维的过滤器,它的维度是 3×3×3,这样这个过滤器也有三层,对应红绿、蓝三个通道。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第8张图片

        为了计算这个卷积操作的输出,你要做的就是把这个 3×3×3 的过滤器先放到最左上角的位置,这个 3×3×3 的过滤器有 27 个数,27 个参数就是 3 的立方。依次取这 27 个数,然后乘以相应的红绿蓝通道中的数字。先取红色通道的前 9 个数字,然后是绿色通道,然后再是蓝色通道,乘以左边黄色立方体覆盖的对应的 27 个数,然后把这些数都加起来,就得到了输出的第一个数字。如果要计算下一个输出,你把这个立方体滑动一个单位,再与这 27 个数相乘,把它们都加起来,就得到了下一个输出,以此类推这个的输出会是一个 4×4 的图像,注意是 4×4×1,最后一个数不是 3 了

        现在你已经了解了如何对立方体卷积,还有最后一个概念,对建立卷积神经网络至关重要。就是,如果我们不仅仅想要检测垂直边缘怎么办?如果我们同时检测垂直边缘和水平边缘,还有 45°倾斜的边缘,还有 70°倾斜的边缘怎么做?换句话说,如果你想同时用多个过滤器怎么办?

 

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第9张图片

        (第一个)这可能是一个垂直边界检测器或者是学习检测其他的特征。第二个过滤器可以用橘色来表示,它可以是一个水平边缘检测器。第一个过滤器卷积,可以得到第一个 4×4 的输出,然后卷积第二个过滤器,得到一个不同的 4×4 的输出。我们做完卷积,然后把这两个 4×4 的输出,取第一个把它放到前面,然后取第二个过滤器输出,放到后面。所以把这两个输出堆叠在一起,这样你就都得到了一个 4×4×2 的输出立方体。这里的 2 的来源于我们用了两个不同的过滤器。

        我们总结一下维度,如果你有一个n × n × n c (通道数)的输入图像,在这个例子中就是 6×6×3,这里的n c 就是通道数目,然后卷积上一个 f×f×n c ,这个例子中是 3×3×3,按照惯例,这个(前一个n C )和这个(后一个n c )必须数值相同。然后你就得到了(n-f+1)×(n-f+1)×n c ′ ,这里n c ′ 其实就是下一层的通道数,它就是你用的过滤器的个数,在我们的例子中,那就是 4×4×2。我写下这个假设时,用的步幅为 1,并且没有 padding。如果你用了不同的步幅或者 padding,那么这个 n-f+1 数值会变化。一个过滤器相当于一个特征

5 单层卷积网络(One layer of a convolutional network)

         下面我们构建卷积神经网络的卷积层,我们已经讲了如何通过两个过滤器卷积处理一个三维图像,并输出两个不同的4×4 矩阵。假设使用第一个过滤器进行卷积,得到第一个 4×4 矩阵。使用第二个过滤器进行卷积得到另外一个 4×4 矩阵。最终各自形成一个卷积神经网络层,然后增加偏差,它是一个实数,通过 Python 的广播机制给这 16 个元素都加上同一偏差。然后应用非线性函数,为了说明,它是一个非线性激活函数 ReLU,输出结果是一个 4×4 矩阵。对于第二个 4×4 矩阵,我们加上不同的偏差,它也是一个实数,16 个数字都加上同一个实数,然后应用非线性函数,也就是一个非线性激活函数 ReLU,最终得到另一个 4×4 矩阵。然后重复我们之前的步骤,把这两个矩阵堆叠起来,最终得到一个 4×4×2 的矩阵。我们通过计算,从 6×6×3 的输入推导出一个 4×4×2 矩阵,它是卷积神经网络的一层,把它映射到神经网络中卷积层中的某一层或者一个非卷积神经网络中。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第10张图片

         注意前向传播中一个操作就是,其中,执行非线性函数得到 ,即。这里的输入是,也就是 x,这些过滤器用变量W [1] 表示。在卷积过程中,我们对这 27 个数进行操作,其实是 27×2,因为我们用了两个过滤器,我们取这些数做乘法。实际执行了一个线性函数,得到一个 4×4 的矩阵。卷积操作的输出结果是一个4×4 的矩阵,它的作用类似于W [1] a [0] ,也就是这两个 4×4 矩阵的输出结果,然后加上偏差。

        示例中我们有两个过滤器,也就是有两个特征,因此我们才最终得到一个 4×4×2 的输出。但如果我们用了 10 个过滤器,而不是 2 个,我们最后会得到一个 4×4×10 维度的输出图像,因为我们选取了其中 10 个特征映射,而不仅仅是 2 个,将它们堆叠在一起,形成一个 4×4×10 的输出图像,也就是a [1] 。为了加深理解,我们来做一个练习。假设你有 10 个过滤器,而不是 2 个,神经网络的一层是 3×3×3,那么,这一层有多少个参数呢?我们来计算一下,每一层都是一个 3×3×3 的矩阵,因此每个过滤器有 27 个参数,也就是 27 个数。然后加上一个偏差,用参数 b 表示,现在参数增加到 28 个。上一页幻灯片里我画了 2 个过滤器,而现在我们有 10 个,加在一起是 28×10,也就是 280 个参数。请注意一点,不论输入图片有多大,1000×1000 也好,5000×5000 也好,参数始终都是 280 个。用这 10 个过滤器来提取特征,如垂直边缘,水平边缘和其它特征。即使这些图片很大,参数却很少,这就是卷积神经网络的一个特征,叫作“避免过拟合”。你已经知道到如何提取 10 个特征,可以应用到大图片中,而参数数量固定不变,此例中只有 28 个,相对较少。

6 池化层

        除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性,我们来看一下。下图是最大池化,过滤器是2x2,步幅是2。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第11张图片

       这是对最大池化功能的直观理解,你可以把这个 4×4 输入看作是某些特征的集合,也许不是。你可以把这个 4×4 区域看作是某些特征的集合,也就是神经网络中某一层的非激活值集合。数字大意味着可能探测到了某些特定的特征,左上象限具有的特征可能是一个垂直边缘,一只眼睛。显然左上象限中存在这个特征,这个特征可能是一只猫眼探测器。然而,右上象限并不存在这个特征。最大化操作的功能就是只要在任何一个象限内提取到某个特征,它都会保留在最大化的池化输出里。所以最大化运算的实际作用就是,如果在过滤器中提取到某个特征,那么保留其最大值。如果没有提取到这个特征,可能在右上象限中不存在这个特征,那么其中的最大值也还是很小,这就是最大池化的直观理解。实际上,梯度下降没有什么可学的,一旦确定了 f 和 s,它就是一个固定运算,梯度下降无需改变任何值。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第12张图片

        以上就是一个二维输入的最大池化的演示,如果输入是三维的,那么输出也是三维的。例如,输入是 5×5×2,那么输出是 3×3×2。计算最大池化的方法就是分别对每个通道执行刚刚的计算过程。一般来说,如果输入是 5×5×n c ,输出就是 3×3×n c ,n c 个通道中每个通道都单独执行最大池化计算,以上就是最大池化。总结一下,池化的超级参数包括过滤器大小 f 和步幅 s,常用的参数值为 f=2,s=2,应用频率非常高,其效果相当于高度和宽度缩减一半。目前来说,最大池化比平均池化更常用。

下面是一个卷积神经网络的例子:

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第13张图片

        有几点要注意,第一,池化层和最大池化层没有参数;第二卷积层的参数相对较少,前面我们提到过,其实许多参数都存在于神经网络的全连接层。观察可发现,随着神经网络的加深,激活值尺寸会逐渐变小,如果激活值尺寸下降太快,也会影响神经网络性能。示例中,激活值尺寸在第一层为 6000,然后减少到 1600,慢慢减少到 84,最后输出 softmax结果。我们发现,许多卷积网络都具有这些属性,模式上也相似。

7 为什么使用卷积

        和只用全连接层相比,卷积层的两个主要优势在于参数共享和稀疏连接,举例说明一下。从上节的表格中我们就可以得出,使用卷积层的参数比全连接层的参数少很多。卷积网络映射这么少参数有两个原因,一是参数共享。观察发现,特征检测如垂直边缘检测如果适用于图片的某个区域,那么它也可能适用于图片的其他区域。也就是说,如果你用一个 3×3 的过滤器检测垂直边缘,那么图片的左上角区域,以及旁边的各个区域都可以使用这个 3×3 的过滤器。每个特征检测器以及输出都可以在输入图片的不同区域中使用同样的参数,以便提取垂直边缘或其它特征。

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第14张图片

        使得卷积网络参数相对较少的第二个方法是使用稀疏连接,我来解释下。这个 0 是通过3×3 的卷积计算得到的,它只依赖于这个 3×3 的输入的单元格,右边这个输出单元(元素0)仅与 36 个输入特征中 9 个相连接。而且其它像素值都不会对输出产生任影响,这就是稀疏连接的概念。

完整的卷积神经网络结构;

卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现_第15张图片

8 用 tensorflow 搭建卷积神经网络实现手写数字识别

https://github.com/xiaooudong/tensorflow_cnn_mnist

你可能感兴趣的:(卷积神经网络 ( Foundations of Convolutional Neural Networks )+ tensorflow案例实现)