本文简单翻译了Dr.Adrian Rosebrock的Deep Learning for Compute Vision一书的介绍及技术部分。如需原书pdf版请联系我。
这本书不仅适合初学者,也有先进的内容。对于这本书中的每一章,作者提供了一系列的学术参考资料,可以用来进一步扩充你的知识。使用Python的深度学习用于计算机视觉的许多章节实际上以易于理解和消化的方式解释了这些学术概念。最重要的是,作者在本书中提供的解决方案和策略可以直接应用到你目前的工作和研究中。一旦您将知识应用到项目/研究中,“深度学习用于计算机视觉(使用Python)”可以节省时间,减少付出更多的代价。
写这本书的灵感之一是演示如何使用现有的深度学习库来构建我们自己的基于Python的自定义工具集,从而使我们能够训练我们自己的深度学习网络。然而,这本书不只是任何深度学习工具包。这个工具包和作者在过去几年中开发并改进的工具包完全一样,是作者自己进行深度学习研究和开发的。当我们通过这本书学习时,我们将一次构建这个工具集的组件。在用Python深入学习计算机视觉的时候,我们的工具集将能够:
1、从磁盘加载图像数据集,将它们存储在内存中,或者将它们写入优化的数据库格式。
2、预处理图像,使得它们适合于训练卷积神经网络。
3、创建一个蓝图类,它可以用来构建我们自己的卷积神经网络的自定义实现。
4、手工实现流行的CNN体系结构,如AlexNet、VGGNet、GoogLeNet、ResNet和SqueezeNet(并从头开始培训)。
5、…还有更多!
2.2分层特征学习
机器学习算法(一般)分为三个阵营——有监督的、无监督的和半监督学习。我们将在本章中讨论有监督和无监督学习,同时保留半监督学习以供将来讨论。
在有监督的情况下,机器学习算法给出了一组输入和目标输出。然后,该算法尝试学习可用于自动将输入数据点映射到其正确目标输出的模式。有监督的学习类似于让老师看着你参加考试。鉴于你之前的知识,你尽力在考试中给正确答案打分;然而,如果你错了,你的老师会指导你下次进行更好更有教养的猜测。
在无监督的情况下,机器学习算法试图在不提示输入是什么的情况下自动发现可区分的特征。在这个场景中,我们的学生试图将类似的问题和答案分组在一起,即使学生不知道正确的答案是什么,并且老师不在那里为他们提供真实的答案。无监督学习显然比监督学习更具挑战性——通过知道答案(即目标输出),我们可以更容易地定义能够将输入数据映射到正确目标分类的区分模式。
在每种情况下,手动定义算法来量化和编码图像的特定方面(即,形状、纹理、颜色等)。给定像素的输入图像,我们将我们的手定义算法应用到像素,并返回接收量化图像内容的特征向量。图像像素本身不服务于输入到我们的特征提取过程。特征提取产生的特征向量是我们真正感兴趣的,因为它们作为机器学习模型的输入。
深度学习,特别是卷积神经网络,采取了不同的方法。代替手工定义一组规则和算法来提取图像的特征,这些特征是从训练过程中自动学习的。让我们再次回到机器学习的目标:计算机应该能够从他们试图解决的问题的经验(例如,样本)中学习。
通过深度学习,我们试图用概念层次来理解问题。每个概念都是建立在其他概念之上的。网络的较低层中的概念编码了问题的一些基本表示,而较高层使用这些基本层来形成更抽象的概念。这种分层学习允许我们完全去除手工设计的特征提取过程,并将CNN作为端到端的学习器对待。给定图像,我们将像素强度值作为输入提供给CNN。使用一系列隐藏层从输入图像中提取特征。这些隐藏的层以分层的方式彼此构建。首先,仅在网络的较低层中检测到边缘状区域。这些边缘区域用于定义角(其中边缘相交)和轮廓(物体的轮廓)。结合角和轮廓可以在下一层对“对象部分”抽象轮廓。
深度学习和卷积神经网络的主要好处之一是它允许我们跳过特征提取步骤,而专注于训练网络来学习这些滤波器的过程。然而,正如我们将在本书后面发现的,训练网络以获得给定图像数据集上的合理精度并不总是一件容易的任务。
2.3深度有多“深”
简短的回答是,专家们对于深度网络的深度没有共识。
现在我们需要研究网络类型的问题。根据定义,卷积神经网络(CNN)是一种深度学习算法。但是,假设我们有一个只有一个卷积层的CNN——是一个浅的网络,但是仍然属于深度学习阵营中的一系列算法,这些算法被认为是“深”的?我个人的观点是,任何具有两个以上隐藏层的网络都可以被认为是“深”的。我的推理是基于以前的研究,其中有严重障碍:
1、我们缺少大型的、标记的数据集可用于培训。
2、我们的计算机太慢,无法训练大的神经网络。
3、不充分的激活函数
现在,我们可以构建更深层次的神经网络,并用更多的数据来训练他们。随着网络深度的增加,分类精度也随之提高。这种行为不同于传统的机器学习算法(即,逻辑回归、SVM、决策树等),其中即使可用训练数据增加,我们的性能也达到高峰。Andrew曾说,科学家们应该知道关于深度学习的数据,如图2.8所示,提供了这种行为的一个例子。
3.图像基础
3.1像素
这里关于像素的介绍以及RGB色彩空间的介绍我就省略了,有需要的请自己阅读原文,图像基础处理推荐阅读数字图像处理的相关内容。
正如我们现在知道的,RGB图像由三个值表示,分别为红色、绿色和蓝色分量的一个。我们可以将一个RGB图像概念化为由宽度W和高度H的三个独立矩阵组成,每个RGB组件一个,如图3.5所示。我们可以组合这三个矩阵来获得具有形状W H D的多维阵列,其中D是通道的深度或数量(对于RGB颜色空间,D=3):
请记住,图像的深度与神经网络的深度非常不同——这一点将在我们开始训练我们自己的卷积神经网络时变得清晰。
然而,暂时只需要理解你将要处理的绝大多数图像是:在RGB颜色空间中由三个通道表示,每个通道在[0;255]的范围内。RGB图像中的给定像素是三个整数的列表:一个值为红色,第二个为绿色,最后一个值为蓝色。编程定义为具有宽度、高度和深度的三维数字阵列。
3.2 图像坐标系
图3.6提供了这个“图形纸”表示的视觉表示。在这里,我们有一个字母“I”在我们的一张图表纸上。我们看到这是一个8*8的网格,总共有64个像素。重要的是要注意,Python语言是零索引的,这意味着我们总是从零开始计数。记住这一点,因为以后你会避免很多混乱(特别是如果你来自Matlab环境)。作为零索引的示例,考虑右侧的像素4列5行的点由点(3,4)索引。
3.2 Numpy数组图像
像OpenCV和scikit-image这样的图像处理库将RGB图像表示为具有形状(高度、宽度、深度)的多维NumPy数组。第一次使用图像处理库的读者常常对这种表示方式感到困惑——当我们通常从宽度优先于高度来考虑图像时,为什么高度在宽度之前呢?答案是因为矩阵符号。
在定义矩阵的维数时,我们总是把它写成行X列。图像中的行数是其高度,而列的数目是图像的宽度。深度仍将保持深度。
因此,虽然看到NumPy数组的形状表示为(高度、宽度、深度)可能有点令人困惑,但是当考虑如何构造和注释矩阵时,这种表示实际上具有直观的意义。
例如,让我们看一下OpenCV库和用于从磁盘加载图像并显示其尺寸的cv2.imread函数:
在这里,我们从磁盘加载名为example.png的图像并将其显示到屏幕上,我的终端输出如下:
该图像的宽度为300像素(列数),高度为248像素(行数),深度为3(通道数)。为了从图像中访问单个像素值,我们使用简单的Numpy数组索引:
要注意OpenCV以相反的顺序存储RGB信道。虽然我们通常认为红色,绿色和蓝色,OpenCV实际上存储像素值在蓝色,绿色,红色的顺序。
为什么OpenCV会这么做?答案纯粹是历史原因。OpenCV库的早期开发人员选择BGR颜色格式,因为BGR顺序在当时照相机制造商和其他软件开发人员中很流行。简单地说,这个BGR顺序是出于历史原因和我们现在不得不选择的。这是一个小小的警告,但在使用OpenCV时要牢记的一个重要的问题。
3.3 尺度与纵横比
图像纵横比伸缩对后期图像识别很重要,比如图3.8,不同的拉伸压缩变化会使图像发生形变或失真而难以识别:
哪种方法最好?简而言之,这要看情况而定。对于一些数据集,您可以简单地忽略纵横比,在通过网络提供图像之前,对图像进行压缩、扭曲和压缩。在其他数据集上,通过沿着最短维度调整大小然后裁剪中心来进一步预处理它们是有利的。我们将在本书的后面更详细地回顾这两种方法(以及如何实现它们),但是现在介绍这个主题很重要,因为我们正在研究图像的基本原理以及如何表示它们。