Deep Computer Vision Using Convolutional Neural Networks

在本章中,我们将探讨CNN的来源,其构造块的外观以及如何使用TensorFlow和Keras实施它们。然后,我们将讨论一些最佳的CNN架构以及其他视觉任务,包括对象检测(对图像中的多个对象进行分类并在其周围放置边框)和语义分割(根据对象的类别对每个像素进行分类)。

视觉皮层的架构

David H. Hubel和Torsten Wiesel分别在19581年和19592年(以及几年后在猴子上)对猫进行了一系列实验,对视觉皮层的结构提供了重要的见识(作者获得了诺贝尔生理学或医学奖。特别是,他们表明视觉皮层中的许多神经元具有较小的局部感受野,这意味着它们仅对位于视野有限区域内的视觉刺激做出反应(见图,其中五个局部感受野神经元由虚线圆圈表示)。不同神经元的感受野可能会重叠,并且它们会共同覆盖整个视野。
视觉皮层中的生物神经元对视域中称为感受野的小区域中的特定模式做出反应;当视觉信号通过连续的大脑模块进入时,神经元会在更大的感受野中响应更复杂的模式。
在这里插入图片描述
这些对视觉皮层的研究激发了1980年推出的新认知加速器,新认知加速器逐渐演变成我们现在所说的卷积神经网络。一个重要的里程碑是Yann LeCun等人在1998年发表的论文。引入了著名的LeNet-5架构,银行广泛使用该架构来识别手写支票号码。该体系结构具有一些您已经知道的构造块,例如全连接层和sigmoid激活函数,但是它还引入了两个新的构造块:卷积层和池化层。让我们现在来看它们。
注意:
为什么不简单地使用具有全连接层的深度神经网络来执行图像识别任务呢?不幸的是,尽管这对于较小的图像(例如MNIST)效果很好,但由于需要大量的参数,因此对于较大的图像却无法使用。例如,一个100×100像素的图像有10,000个像素,如果第一层只有1,000个神经元(已经严重限制了传输到下一层的信息量),则意味着总共有1000万个连接。并且那只是第一层。但CNN使用部分连接的层和权重共享解决了此问题。

卷基层 (Convolutional Layers)

CNN的最重要组成部分是卷积层:第一个卷积层中的神经元不连接到输入图像中的每个像素,而仅连接到其接收域中的像素(见图)。反过来,第二卷积层中的每个神经元仅连接到位于第一层小矩形内的神经元。这种体系结构允许网络将注意力集中在第一个隐藏层中的小型低级功能,然后将它们组合到下一个隐藏层中的较大的高级功能,依此类推。这种分层结构在现实世界的图像中很常见,这就是CNN如此出色地用于图像识别的原因之一。
在这里插入图片描述

注意:

到目前为止,我们所研究的所有多层神经网络都具有由一长列神经元组成的层,我们必须将输入图像展平为一维,然后再将其馈送到神经网络。在CNN中,每一层均以2D表示,这使得将神经元与其相应的输入进行匹配变得更加容易。
位于给定层的第i行第j列的神经元与位于第i到i + fh – 1列的第j到j + fw – 1行的前一层的神经元的输出连接,其中fh和fw为感受野的高度和宽度(见图)。为了使层与上一层具有相同的高度和宽度,通常在输入周围添加零,如图所示。这称为零填充(zero padding)。
在这里插入图片描述
也可以通过隔开感受域来将较大的输入层连接到较小的层。这大大降低了模型的计算复杂度。从一个感受域到另一个感受域的转变称为步幅(stride):
在这里插入图片描述

过滤器或卷积核(filters)

神经元的权重可以表示为一幅小图像,大小相当于感受野的大小。例如,下图显示了两个可能的权重集,称为过滤器(或卷积内核)。第一个表示为一个黑色的正方形,中间有一条垂直的白线(这是一个7×7的矩阵,除中间的列(全为1s)外,其余的全为0;使用这些权重的神经元将忽略其接收场中除中心垂直线以外的所有内容(因为所有输入都将乘以0,位于中心垂直线中的输入除外)。第二个过滤器是一个黑色的正方形,中间有一条水平的白线。再次,使用这些权重的神经元将忽略除了中心水平线以外的其感受野中的所有内容。
现在,如果层中的所有神经元都使用相同的垂直线滤波器(和相同的偏差项),并且向网络馈入下图中所示的输入图像(底部图像),则该层将输出左上方的图像。请注意,垂直白线得到增强,而其余部分变得模糊。同样,如果所有神经元都使用相同的水平线滤波器,则将获得右上方的图像。请注意,水平的白线得到增强,而其余部分被模糊掉。因此,使用相同滤镜的充满神经元的图层会输出一个特征图(feature map),该图突出显示图像中过滤的区域。当然,您不必手动定义过滤器:相反,在训练过程中,卷积层将自动学习对其任务最有用的过滤器,而上面的层将学习将它们组合成更复杂的模式。
在这里插入图片描述

堆叠多个特征图(Stacking Multiple Feature Maps)

到目前为止,为简单起见,我将每个卷积层的输出表示为2D层,但实际上,卷积层具有多个滤镜(您可以决定多少个)并为每个滤镜输出一个特征图,因此可以更精确地表示它以3D模式显示(见下图)。它在每个特征图中每个像素有一个神经元,并且给定特征图中的所有神经元共享相同的参数(即,相同的权重和偏差项)。不同特征图中的神经元使用不同的参数。神经元的感受野与前面描述的相同,但它跨越了先前所有图层的特征图。简而言之,卷积层同时将多个可训练的滤波器应用于其输入,从而使其能够检测其输入中任何位置的多个特征。

注意:

特征图中所有神经元共享相同参数的事实大大减少了模型中参数的数量。 CNN学会了在一个位置识别模式后,便可以在其他任何位置识别模式。相反,常规DNN一旦学会了在一个位置识别模式,就只能在那个特定位置识别它。
输入图像也由多个子层组成:每个颜色通道一个。通常有三种:红色,绿色和蓝色(RGB)。灰度图像只有一个通道,但是某些图像可能具有更多通道,例如,捕获额外光频率(例如红外)的卫星图像。
在这里插入图片描述

TensorFlow Implementation

在TensorFlow中,每个输入图像通常表示为形状[height, width, channels]的3D张量。mini-batch表示为形状 [mini-batch size, height, width, channels]的4D张量。卷积层的权重表示为形状为[fh,fw,fn’,fn]的4D张量。卷积层的偏置项简单表示为形状[fn]的一维张量。
让我们看一个简单的例子。下面的代码使用Scikit-Learn的load_sample_image()加载两个示例图像(加载两个彩色图像,一个是中国庙宇,另一个是花朵),然后创建两个滤镜并将其应用于两个图像,最后它显示特征图:

from sklearn.datasets import load_sample_image 
# Load sample images 
china = load_sample_image("china.jpg") / 255
flower = load_sample_image("flower.jpg") / 255 images = np.array([china, flower]) batch_size, height, width, channels = images.shape 
# Create 2 filters 
filters = np.zeros(shape=(7, 7, channels, 2), dtype=np.float32) filters[:, 3, :, 0] = 1 
# vertical line 
filters[3, :, :, 1] = 1 
# horizontal line 
outputs = tf.nn.conv2d(images, filters, strides=1, padding="same") 
plt.imshow(outputs[0, :, :, 1], cmap="gray") 
# plot 1st image's 2nd feature map plt.show()
  1. 每个颜色通道的像素强度表示为从0到255的字节,因此我们仅需除以255即可缩放这些功能,以得到从0到1的浮点数。
  2. 然后,我们创建两个7×7滤镜(一个在中间带有垂直白线,另一个在中间带有水平白线)。
  3. 我们使用tf.nn.conv2d()函数将它们应用于两个图像,该函数是TensorFlow的底层深度学习API的一部分。在此示例中,我们使用零填充(padding =“ same”)和跨度为2。
    在这里插入图片描述
    在此示例中,我们手动定义了过滤器,但是在实际的CNN中,通常会将过滤器定义为可训练变量,以便神经网络可以了解哪种过滤器效果最好,如前所述。而不是手动创建变量,请使用keras.layers.Conv2D层:
conv = keras.layers.Conv2D(filters=32, kernel_size=3, strides=1, padding="same", activation="relu")

这段代码使用跨度为1(包括水平和垂直)和“same”的填充和32个滤镜创建一个Conv2D层,每个滤镜为3×3,并使用“same”填充,并将ReLU激活功能应用于其输出。如您所见,卷积层具有很多超参数:您必须选择过滤器的数量,其高度和宽度,步幅和填充类型。与往常一样,您可以使用交叉验证来找到正确的超参数值,但这非常耗时。稍后我们将讨论通用的CNN架构,以使您了解哪些超参数值在实践中最有效。

Memory Requirements

CNN的另一个问题是卷积层需要大量的RAM。在训练期间尤其如此,因为反向传播的反向传递需要在正向传递期间计算的所有中间值。
例如,考虑一个带5×5滤镜的卷积层,输出200个大小为150×100的特征贴图,并带有跨步1和“相同”的填充。如果输入是150×100 RGB图像(三个通道),则参数数量为(5×5×3 + 1)×200 = 15,200(+1对应于偏置项),200个特征图中的每个特征图都包含150×100个神经元,并且每个这些神经元都需要计算其5×5×3 = 75个输入的加权和:总共为2.25亿个浮点乘法。相比之下,不如完全连接的层那么糟糕,但仍然需要大量的计算。此外,如果使用32位浮点数表示特征图,则卷积层的输出将占用200×150×100×32 = 96百万位(12 MB)的RAM。这仅是一个实例,如果一个培训批次包含100个实例,则该层将使用1.2 GB的RAM!
在推论期间(即,对新实例进行预测时),只要计算了下一层,就可以释放一层占用的RAM,因此您只需要两个连续层所需的RAM。但是在训练过程中,需要保留在前向遍历中计算出的所有内容以用于反向遍历,因此所需的RAM数量至少是所有层所需的RAM总量。

Pooling Layers

一旦了解了卷积层如何工作,池化层就很容易掌握。他们的目标是对输入图像进行二次采样(即缩小),以减少计算量,内存使用量和参数数量(从而限制过拟合的风险)。
就像在卷积层中一样,池化层中的每个神经元都连接到位于一个小的矩形接受场中的上一层中有限数量的神经元的输出。您必须像以前一样定义其大小,步幅和填充类型。但是,合并的神经元没有权重。它所做的全部工作就是使用汇总函数(例如最大值或均值)汇总输入。图14-8显示了最大池化层,它是池化层的最常见类型。在此示例中,我们使用2×2池内核,步幅为2,没有填充。只有每个接受域中的最大输入值才可进入下一层,而其他输入则被丢弃。例如,在图14-8的左下接受域中,输入值为1、5、3、2,因此只有最大值5传播到下一层。由于跨度为2,因此输出图像的高度为输入图像的一半,宽度为宽度的一半(由于不使用填充,因此四舍五入)。
在这里插入图片描述

注意:

池化层通常在每个输入通道上独立工作,因此输出深度与输入深度相同。
如图14-9所示,除了减少计算量,内存使用量和参数数量之外,最大池化层还为小型转换引入了一定程度的不变性。在这里,我们假设亮像素的值比暗像素的值低,并且我们考虑了三个图像(A,B,C)经过一个具有2×2内核且跨度为2的最大池化层。图像B和C相同如图A所示,但向右移动了一两个像素。如您所见,图像A和B的最大池化层的输出是相同的。这就是翻译不变性的含义。对于图像C,输出是不同的:它向右移动了一个像素(但仍然有75%的不变性)。通过在CNN中每隔几层插入一个最大池化层,就可以在更大范围内获得某种程度的平移不变性。而且,最大池化提供了少量的旋转不变性和轻微的尺度不变性。在预测不应该依赖这些细节的情况下(例如在分类任务中),这种不变性(即使受到限制)也很有用。
在这里插入图片描述
但是,最大池化也有一些缺点。首先,它显然是非常具有破坏性的:即使使用2×2的微小内核并且步幅为2,输出在两个方向上都将缩小两倍(因此其面积将缩小四倍),仅减少输入的75%价值观。并且在某些应用中,不变性是不可取的。进行语义分割(根据像素所属的对象对图像中的每个像素进行分类的任务):显然,如果输入图像向右平移一个像素,则输出还应向右平移一个像素。在这种情况下,目标是等方差,而不是不变性:输入的微小变化应导致输出的相应微小变化。

max_pool = keras.layers.MaxPool2D(pool_size=2)
output = tf.nn.max_pool(images, ksize=(1, 1, 1, 3), strides=(1, 1, 1, 3), padding="valid")

CNN Architectures

典型的CNN架构堆叠了几个卷积层(通常每个卷积层之后都是ReLU层),然后是池化层,然后是另外几个卷积层(+ ReLU),然后是另一个池化层,依此类推。随着图像在网络中的传播,图像变得越来越小,但是由于卷积层的存在,图像通常也会变得越来越深(即具有更多的特征图)(见图14-11)。在堆栈的顶部,添加了常规前馈神经网络,该网络由几个完全连接的层(+ ReLU)组成,最后一层输出预测(例如,输出估计类概率的softmax层)。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值