Python 深度学习(二)(1)

简介: Python 深度学习(二)

第五章:图像识别

视觉可以说是人类最重要的感官之一。我们依赖视觉来识别食物,逃离危险,认出朋友和家人,以及在熟悉的环境中找到方向。我们甚至依赖视觉来阅读这本书,并识别其中打印的每一个字母和符号。然而,图像识别一直以来一直是计算机科学中最困难的问题之一。因为要教会计算机如何识别不同的物体是非常困难的,因为很难向机器解释构成指定物体的特征。然而,正如我们所看到的,深度学习中的神经网络通过自身学习,也就是学会了构成每个物体的特征,因此非常适合图像识别这样的任务。

在本章中,我们将涵盖以下主题:

  • 人造模型和生物模型之间的相似之处
  • CNN 的直觉和理由
  • 卷积层
  • 池层
  • 丢弃
  • 深度学习中的卷积层

人造模型和生物模型之间的相似之处

人类视觉是一个复杂且结构严谨的过程。视觉系统通过视网膜、丘脑、视觉皮层和颞下皮质等阶级性地理解现实。视网膜的输入是一个二维的颜色密度数组,通过视神经传递到丘脑。丘脑除了嗅觉系统的感官信息外,还接收从视网膜收集的视觉信息,然后将该信息传递到初级视觉皮层,也就是 V1 区,它提取基本信息,例如线条和运动方向。然后信息流向负责色彩解释和不同光照条件下的颜色恒定性的 V2 区,然后到达 V3 和 V4 区,改善色彩和形态感知。最后,信息传递到颞下皮质IT),用于物体和面部识别(事实上,IT 区域还进一步细分为三个亚区,即后部 IT、中央 IT 和前部 IT)。因此,大脑通过在不同层级处理信息来处理视觉信息。我们的大脑似乎通过在不同层级上创建简单的抽象现实表示,然后将它们重新组合在一起来解决这个问题(详细参考:J. DiCarlo, D. Zoccolan, and N. Rust, 大脑是如何处理视觉物体识别的?www.ncbi.nlm.nih.gov/pmc/articles/PMC3306444)。

我们目前看到的深度学习神经网络通过创建抽象表示来工作,就像我们在 RBM 中看到的那样,但是理解感官信息的重要拼图中还有另一个重要部分:我们从感官输入中提取的信息通常主要由最相关的信息确定。从视觉上看,我们可以假设附近的像素是最相关的,它们的集体信息比我们从彼此非常遥远的像素中得出的信息更相关。在理解语音方面,我们已经讨论过研究三音素的重要性,也就是说,对音频的理解依赖于其前后的声音。要识别字母或数字,我们需要理解附近像素的依赖性,因为这决定了元素的形状,从而区分例如 0 和 1 等之间的差异。总的来说,远离 0 的像素通常对我们理解数字"0"没有或几乎没有影响。卷积网络的构建正是为了解决这个问题:如何使与更近的神经元相关的信息比来自更远的神经元更相关的信息。在视觉问题中,这意味着让神经元处理来自附近像素的信息,并忽略与远离像素相关的信息。

直觉和理解

我们在第三章中已经提到了 Alex Krizhevsky、Ilya Sutskever 和 Geoffrey Hinton 在 2012 年发表的论文:使用深度卷积神经网络进行 ImageNet 分类。尽管卷积的起源可以追溯到 80 年代,但那是第一篇突出卷积网络在图像处理和识别中深刻重要性的论文之一,当前几乎没有用于图像识别的深度神经网络可以在没有某些卷积层的情况下工作。

我们在使用传统前馈网络时遇到的一个重要问题是它们可能会过拟合,特别是在处理中等到大型图像时。这通常是因为神经网络具有非常多的参数,事实上,在经典神经网络中,一层中的所有神经元都连接到下一层中的每一个神经元。当参数数量很大时,过拟合的可能性更大。让我们看以下图片:我们可以通过画一条穿过所有点的线来拟合数据,或者更好的是,一条不完全匹配数据但更可能预测未来示例的线。


图中的点表示输入数据点。虽然它们明显遵循抛物线的形状,但由于数据中的噪声,它们可能不会被精确地绘制到抛物线上。

在两幅图中的第一个例子中,我们对数据进行了过拟合。在第二个例子中,我们已经将我们的预测与数据匹配得更好,这样我们的预测更有可能更好地预测未来的数据。在第一种情况下,我们只需要三个参数来描述曲线:y = ax² + bx + c,而在第二种情况下,我们需要比三个参数多得多的参数来编写该曲线的方程。这直观地解释了为什么有时候拥有太多参数可能不是一件好事,而且可能导致过拟合。对于像 cifar10 示例中那样小的图像(cifar10 是一个经过验证的计算机视觉数据集,由 60000 张 32 x 32 图像组成,分为 10 类,在本章中我们将看到该数据集的几个示例),经典的前馈网络的输入大小为 3 x 32 x 32,已经约为简单 mnist 数字图像的四倍。更大的图像,比如 3 x 64 x 64,将拥有大约 16 倍于输入神经元数量的连接权重:


在左图中,我们画了一条与数据完全匹配的直线。在第二个图中,我们画了一条近似连接数据点形状的直线,但并不完全匹配数据点。尽管第二条曲线在当前输入上不够精确,但比第一张图中的曲线更有可能预测未来的数据点。

卷积网络减少了所需的参数数量,因为它们要求神经元仅在本地与对应于相邻像素的神经元连接,因此有助于避免过拟合。此外,减少参数数量也有助于计算。在下一节中,我们将介绍一些卷积层的示例来帮助理解,然后我们将正式定义它们。

卷积层

卷积层(有时在文献中称为 “滤波器”)是一种特殊类型的神经网络,它操作图像以突出显示某些特征。在深入了解细节之前,让我们使用一些代码和一些示例介绍一个卷积滤波器。这将使直觉更简单,也将更容易理解理论。为此,我们可以使用 keras 数据集,这使得加载数据变得容易。

我们将导入 numpy,然后是 mnist 数据集,以及 matplotlib 来展示数据:

import numpy 
from keras.datasets import mnist  
import matplotlib.pyplot as plt 
import matplotlib.cm as cm

让我们定义我们的主函数,该函数接受一个整数,对应于 mnist 数据集中的图像,以及一个滤波器,这种情况下我们将定义 blur 滤波器:

def main(image, im_filter):
      im = X_train[image]

现在我们定义一个新的图像 imC,大小为 (im.width-2, im.height-2)

width = im.shape[0]       
      height = im.shape[1]
      imC = numpy.zeros((width-2, height-2))

此时我们进行卷积,我们将很快解释(正如我们将看到的,实际上有几种类型的卷积取决于不同的参数,现在我们只是解释基本概念,并稍后详细介绍):

for row in range(1,width-1):
          for col in range(1,height-1):
              for i in range(len(im_filter[0])):
                  for j in range(len(im_filter)):
                      imC[row-1][col-1] += im[row-1+i][col-1+j]*im_filter[i][j]
              if imC[row-1][col-1] > 255:
                  imC[row-1][col-1] = 255
              elif imC[row-1][col-1] < 0:
                  imC[row-1][col-1] = 0 

现在我们准备显示原始图像和新图像:

plt.imshow( im, cmap = cm.Greys_r )         
      plt.show()
      plt.imshow( imC/255, cmap = cm.Greys_r )       
      plt.show()

现在我们准备使用 Keras 加载mnist数据集,就像我们在第三章中所做的那样,深度学习基础。此外,让我们定义一个滤波器。滤波器是一个小区域(在本例中为 3 x 3),每个条目定义一个实数值。在这种情况下,我们定义一个所有条目值都相同的滤波器:

blur = [[1./9, 1./9, 1./9], [1./9, 1./9, 1./9], [1./9, 1./9, 1./9]]

由于我们有九个条目,我们将值设置为 1/9 以归一化值。

我们可以对任何图像(用一个表示位置的整数表示)调用main函数在这样一个数据集中:

if __name__ == '__main__':          
    (X_train, Y_train), (X_test, Y_test) = mnist.load_data()
    blur = [[1./9, 1./9, 1./9], [1./9, 1./9, 1./9], [1./9, 1./9, 1./9]]
    main(3, blur)

让我们看看我们做了什么。我们将滤波器的每个条目与原始图像的一个条目相乘,然后将它们全部加起来得到一个单一的值。由于滤波器的大小小于图像的大小,我们将滤波器移动 1 像素,并继续执行此过程,直到覆盖整个图像。由于滤波器由所有等于 1/9 的值组成,实际上我们已经用接近它的值的值平均了所有输入值,这就有了模糊图像的效果。

这就是我们得到的:


顶部是原始 mnist 图像,底部是我们应用滤波器后的新图像

在选择滤波器时,我们可以使用任何值;在这种情况下,我们使用的是全部相同的值。但是,我们可以使用不同的值,例如仅查看输入的相邻值,将它们相加,并减去中心输入的值。让我们定义一个新的滤波器,并将其称为边缘,如下所示:

edges = [[1, 1, 1], [1, -8, 1], [1, 1, 1]]

如果我们现在应用此滤波器,而不是之前定义的模糊滤波器,则会得到以下图像:


顶部是原始 mnist 图像,底部是我们应用滤波器后的新图像

因此很明显,滤波器可以改变图像,并显示可以用于检测和分类图像的“特征”。例如,要对数字进行分类,内部的颜色并不重要,而诸如“边缘”之类的滤波器有助于识别数字的一般形状,这对于正确分类是重要的。

我们可以将滤波器视为与神经网络相同,认为我们定义的滤波器是一组权重,并且最终值表示下一层中神经元的激活值(实际上,尽管我们选择了特定的权重来讨论这些示例,但我们将看到权重将通过反向传播由神经网络学习):


滤波器覆盖了一个固定的区域,对于该区域中的每个神经元,它定义了与下一层中的神经元的连接权重。然后,下一层中的神经元将具有输入值,该输入值等于通过相应的连接权重中介的所有输入神经元的贡献总和计算得到的常规激活值。

然后我们保持相同的权重,滑动滤波器,生成一个新的神经元集,这些神经元对应于过滤后的图像:


我们可以不断重复这个过程,直到我们移动到整个图像上,我们可以使用尽可能多的滤波器重复这个过程,创建一组新的图像,每个图像都会突出显示不同的特征或特性。虽然我们在示例中没有使用偏置,但也可以向滤波器添加偏置,这将添加到神经网络中,我们还可以定义不同的活动函数。在我们的代码示例中,您会注意到我们强制值保持在范围(0, 255)内,这可以被认为是一个简单的阈值函数:


当滤波器在图像上移动时,我们为输出图像中的神经元定义新的激活值。

由于可以定义许多滤波器,因此我们应该将输出视为一组图像,每个滤波器定义一个图像。如果我们仅使用“边缘”和“模糊”滤波器,则输出层将有两个图像,每个选择的滤波器一个。因此,输出将除了宽度和高度外,还具有等于选择的滤波器数的深度。实际上,如果我们使用彩色图像作为输入,输入层也可以具有深度;图像实际上通常由三个通道组成,在计算机图形中用 RGB 表示,红色通道、绿色通道和蓝色通道。在我们的示例中,滤波器由二维矩阵表示(例如模糊滤波器是一个 3 x 3 矩阵,所有条目都相等于 1/9)。然而,如果输入是彩色图像,则滤波器也将具有深度(在这种情况下等于三,即颜色通道的数量),因此将由三个(颜色通道数)3 x 3 矩阵表示。一般来说,滤波器因此将由一个三维数组表示,具有宽度、高度和深度,有时被称为“体积”。在前面的示例中,由于mnist图像仅为灰度,因此滤波器的深度为 1。因此,深度为d的通用滤波器由具有相同宽度和高度的d个滤波器组成。这些d个滤波器中的每一个称为“切片”或“叶子”:


类似地,和以前一样,对于每个“叶片”或“片段”,我们连接小的子区域中的每个神经元以及一个偏置到一个神经元,并计算其激活值,其由滤波器中设置的连接权重定义,并滑动滤波器跨整个区域。这样的过程,因为它容易计算,所以需要的参数数量等于滤波器定义的权重数(在我们上面的示例中,这将是 3 x 3 = 9),乘以“叶片”的数量,也就是层的深度,再加上一个偏置。这定义了一个特征图,因为它突出显示了输入的特定特征。在我们上面的代码中,我们定义了两个特征图,一个“模糊”和一个“边缘”。因此,我们需要将参数的数量乘以特征图的数量。请注意,每个滤波器的权重是固定的;当我们滑动滤波器跨区域时,我们不会改变权重。因此,如果我们从尺寸为(宽度,高度,深度)的层开始,以及一个维度为(filter_w,filter_h)的滤波器,那么应用卷积后的输出层是(width - filter_w + 1,height - filter_h + 1)。新层的深度取决于我们想要创建多少特征图。在我们之前的mnist代码示例中,如果我们同时应用了模糊边缘滤波器,我们将拥有一个尺寸为(28 x 28 x 1)的输入层,因为只有一个通道,因为数字是灰度图像,并且一个尺寸为(26 x 26 x 2)的输出层,因为我们的滤波器尺寸为(3 x 3),我们使用了两个滤波器。参数的数量仅为 18(3 x 3 x 2),如果我们添加一个偏置,则为 20(3 x 3 x 2 + 2)。这比我们在传统的前馈网络中所需的要少得多,因为由于输入是 784 像素,一个只有 50 个神经元的简单隐藏层将需要 784 x 50 = 39200 个参数,如果我们添加偏置,则为 39250 个:


我们将滤波器沿着包含在层中的所有“叶片”滑过图像。

此外,卷积层可以更好地工作,因为每个神经元仅从相邻的神经元获得其输入,并且不关心从彼此相距较远的神经元收集输入的情况。

卷积层中的步幅和填充

我们所展示的示例,辅以图片,实际上只讲述了滤波器的一个特定应用(正如我们之前提到的,根据所选参数,有不同类型的卷积)。实际上,滤波器的大小可能会有所不同,以及它在图像上的移动方式以及在图像边缘的行为。在我们的示例中,我们每次将滤波器沿图像移动 1 个像素。我们每次移动滤波器时跳过多少像素(神经元)称为步幅。在上面的示例中,我们使用了步幅为 1,但使用较大的步幅,如 2 甚至更大,也并不罕见。在这种情况下,输出层的宽度和高度将较小:


使用步长为 2 的滤波器应用——滤波器每次移动两个像素。

另外,我们可能也决定部分地在原始图片外应用滤镜。在这种情况下,我们会假设缺失的神经元值为 0。这就是所谓的填充;也就是,在原始图像外部添加值为 0 的神经元。如果我们想要输出图像与输入图像大小相同的话,这可能会很有用。在上面,我们写出了零填充情况下新输出图像大小的公式,即(width - filter_w + 1, height – filter_h + 1),对应输入大小为(width, height)和滤波器尺寸为(filter_w, filter_h)。如果我们在图像的四周使用填充P,输出大小将为(width + 2P - filter_w + 1, height + 2P – filter_h + 1)。总结一下,在每个维度上(无论是宽度还是高度),让输入切片的大小称为I=(I[w](I[h]), 滤波器的大小为F=(F[w],F[h]), 步长的大小为S=(S[w],S[h]), 和填充的大小为P=(P[w],P[h]),那么输出切片的大小*O=(O[w], O[h])就由下式给出:


当然,这也确定了S的约束之一,即它必须在宽度方向和高度方向上都能整除*(I + 2P – F)*。最终体积的尺寸通过乘以所需的特征映射数得到。

相反,使用的参数数目W与步长和填充无关,仅仅是滤波器大小的函数,输入的深度D(切片数量),以及选定的特征映射数量M


使用填充(也称为零填充,因为我们用零填充图像)有时很有用,如果我们希望输出维度与输入维度相同的话。如果我们使用一个大小为(2 x 2)的滤波器,实际上可以清楚地看到通过应用值为 1 的填充和步长为 1,输出切片的尺寸与输入切片的大小相同。

池化层

在前一节中,我们已经推导出了卷积层中每个切片大小的公式。正如我们讨论过的那样,卷积层的优势之一是它减少了所需的参数数量,提升了性能,减少了过拟合。在执行卷积操作后,通常会执行另一个操作——池化。最经典的例子就是最大池化,这意味着在每个切片上创建(2 x 2)的网格,并在每个网格中选择具有最大激活值的神经元,丢弃其他的。很明显,这样的操作会丢弃 75%的神经元,仅保留在每个单元格中贡献最多的神经元。

对于每个汇集层来说有两个参数,类似于卷积层中的步幅和填充参数,它们是单元大小和步幅。一个典型的选择是选择单元大小为 2,步幅为 2,不过选择单元大小为 3,步幅为 2,创建一些重叠也不少见。然而需要注意的是,如果单元大小太大,汇集层可能会丢弃太多信息,这对于帮助并不利。我们可以推导出与我们推导卷积层的公式类似的汇集层输出的公式。\


汇集层不会改变层的体积深度,保持相同数量的片,因为汇集操作是在每个片中独立地进行。

还需要注意的是,类似于我们可以使用不同的激活函数一样,我们也可以使用不同的汇集操作。取最大值是最常见的操作之一,不过取所有值的平均值或者L ²度量也并不少见,这是所有平方的平方根。在实践中,最大汇聚通常表现更好,因为它保留了图像中最相关的结构。

然而需要注意的是,虽然汇集层仍然被广泛使用,有时候只需使用步幅较大的卷积层而不是汇集层,就能达到类似或更好的结果(例如,见 J. Springerberg, A. Dosovitskiy, T. Brox, 和 M. Riedmiller,追求简洁:全卷积网络,(2015),arxiv.org/pdf/1412.6806.pdf)。

然而,如果使用汇集层,它们通常被用于在几个卷积层中间,通常是在每隔一个卷积操作之后。

还需要注意的是,汇集层不会增加新的参数,因为它们只是提取值(如最大值)而不需要额外的权重或偏置:


最大汇聚层的例子:计算每个 2x2 单元的最大值以生成一个新层。

Python 深度学习(二)(2)https://developer.aliyun.com/article/1511969

相关文章
|
7天前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能食品消费模式分析的深度学习模型
使用Python实现智能食品消费模式分析的深度学习模型
97 70
|
9天前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能食品消费习惯分析的深度学习模型
使用Python实现智能食品消费习惯分析的深度学习模型
107 68
|
7天前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
62 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
5天前
|
机器学习/深度学习 数据采集 数据挖掘
使用Python实现智能食品消费市场分析的深度学习模型
使用Python实现智能食品消费市场分析的深度学习模型
68 36
|
1天前
|
机器学习/深度学习 数据采集 搜索推荐
使用Python实现智能食品消费偏好预测的深度学习模型
使用Python实现智能食品消费偏好预测的深度学习模型
32 23
|
8天前
|
机器学习/深度学习 算法 前端开发
基于Python深度学习的果蔬识别系统实现
果蔬识别系统,主要开发语言为Python,基于TensorFlow搭建ResNet卷积神经网络算法模型,通过对12种常见的果蔬('土豆', '圣女果', '大白菜', '大葱', '梨', '胡萝卜', '芒果', '苹果', '西红柿', '韭菜', '香蕉', '黄瓜')图像数据集进行训练,最后得到一个识别精度较高的模型文件。再基于Django框架搭建Web网页端可视化操作界面,以下为项目实现介绍。
18 4
基于Python深度学习的果蔬识别系统实现
|
2天前
|
机器学习/深度学习 数据采集 数据挖掘
使用Python实现智能食品消费习惯预测的深度学习模型
使用Python实现智能食品消费习惯预测的深度学习模型
34 19
|
3天前
|
机器学习/深度学习 数据采集 数据挖掘
使用Python实现智能食品消费趋势分析的深度学习模型
使用Python实现智能食品消费趋势分析的深度学习模型
41 18
|
6天前
|
机器学习/深度学习 数据采集 供应链
使用Python实现智能食品消费需求预测的深度学习模型
使用Python实现智能食品消费需求预测的深度学习模型
32 10
|
4天前
|
机器学习/深度学习 数据采集 搜索推荐
使用Python实现深度学习模型:智能食品消费行为预测
使用Python实现深度学习模型:智能食品消费行为预测
32 8