卷积神经网络——吴恩达深度学习课程笔记(四)

2020-07-20 11:52:25 浏览数 (1)

文章总览图

卷积基础

1,计算机视觉 Computer Vision

计算机视觉(Computer Vision)包含很多不同类别的问题,如图片分类、目标检测、图片风格迁移、人工图片合成等等。

图片分类问题是CV的基本问题。由于图片像素点往往很大,输入特征很多导致需要训练的参数太多,而样本量有限,使用全连接神经网络会面临着严重的过拟合问题。卷积神经网络是解决图片分类问题非常有效的方法,可以在相对较少的样本量情况下训练出很好的分类效果。

2,卷积运算

卷积运算是卷积神经网络的基本组成部分。在图像领域,卷积运算的基本作用是能够检测图像中的某种模式或者说提取特征,例如边缘检测。

以下是一个3*3的卷积核通过卷积运算进行竖直边缘检测的例子。

如上所示,使用卷积运算会使运算后得到的矩阵尺寸缩小,并且位于图像边缘的点参与运算的次数较少,可能会丢失信息。应用填充(padding)可以解决这个问题。在图片边缘周围填入适当的0以保持卷积后图片尺寸不变,这称为 same填充。如果不填充,称为valid填充。

步长stride是卷积运算的另外一个参数。步长是卷积核在图片中每次滑动的长度。一般stride取1,以下是stride取2的例子。

一次卷积后,图片的像素矩阵尺寸将由 n 变成以下大小:

foor((n 2p - f)/ s 1)

在卷积神经网络中,为了提取多个不同的特征模式,每一个卷积层通常会有多个卷积核,每个卷积核和图片进行卷积运算后得到的结果叫做特征图,各个卷积核中的参数在模型中进行学习。

3,池化运算

池化运算是卷积神经网络的另一种重要结构。池化运算的作用主要是下采样,或者简单地说,是为了对图片降维,以减少参数的个数。池化层没有参数需要学习。

池化运算包括最大池化和平均池化。常用的是最大池化。

4,CNN基本结构

这里以 LeNet-5 为例,给出一个完整的卷积神经网络。

卷积神经通常具有以下经典模式:

卷积层和池化层交替排列,然后展开后连接几个全连接层,最后连接softmax分类器。

随着网络的深入,特征图大小将会逐渐减小,但特征图数量(通道数量)逐渐增加。

5,CNN作用原理

CNN有效果的几个基本原理如下:

一是权值共享,二是局部连接,三是平移不变。

所谓权值共享,即当卷积核在图片中滑动时,卷积核的参数是不变的。由于共享权值,卷积层的参数和输入的图片尺寸无关,只和卷积核数量,卷积核尺寸有关,这使得卷积层的参数数量会远远小于对应全连接层的参数数量。

所谓局部连接,即每次卷积运算只检测卷积核尺寸范围的局部特征,这与图片中的关键信息只和局部像素有关很好地适应。

所谓平移不变,即假设目标在图片中发生移动,卷积神经网络计算结果基本不变。这是权值共享和池化运算导致的特性,使网络对空间平移具有鲁棒性。

卷积实例

1,LeNet

LeNet是一个用来识别手写数字灰度图像的最经典的卷积神经网络,是Yann LeCun在1998年设计并提出的。LeNet的网络结构规模较小,但包含了卷积层、池化层、全连接层,它们都构成了现代CNN的基本组件。

2,AlexNet

AlexNet是2012年ILSVRC竞赛冠军获得者Hinton和他的学生Alex Krizhevsky设计的,用于直接处理3通道的彩色图像。AlexNet在ImageNet数据集的top5准确率达到了83.6%,高出了第2名接近10个百分点。也是在那年之后,更多的更深的神经网络被提出。

AlexNet中包含了几个比较新的技术点,如首次在CNN中成功应用了ReLU激活函数,使用Dropout防止过拟合,使用最大池化代替平均池化,使用LRN局部相应归一化,使用数据增强技术,使用GPU进行运算加速等。

对多通道图像运用2D卷积时,同一卷积核要对不同的通道的计算结果按位置坐标求和,以整合各个通道的信息。输出结果的维数与卷积核的参数总数和输入的通道数无关,只与卷积核的数目和维度有关。

3,Vgg16 Net

VGG卷积神经网络是牛津大学和DeepMind在2014年提出来的,在ImageNet数据集的top5准确率达到了92.3%。当这个模型被提出时,由于它的简洁性和实用性,马上成为了当时最流行的卷积神经网络模型。

VGG卷积层都使用3×3,same填充,stride = 1的卷积,池化层都使用2×2的最大池化。这也成为后来主流的卷积核和池化层的参数取值标准。

4,ResNet

ResNet(Residual Neural Network)由微软研究院的Kaiming He等四名华人提出,通过使用ResNet块成功训练出了152层的神经网络,并在ILSVRC2015比赛中取得冠军,在ImageNet数据集top5上的准确率达到了96.43%,同时参数量比VGGNet低,效果非常突出。

ResNet的结构可以极快的加速神经网络的训练,模型的准确率也有比较大的提升。ResNet的主要思想是在网络中增加了直连通道,允许中间激活信息直接传到后面的层中,这样的话直连通道之间的神经网络可以不用学习整个的输出,而是之前网络输出的残差,含有这种shortcut连接的网络模块叫做残差块。

多个残差块堆积起来构成ResNet网络结构,其结构如下:

随着网络层数的加深,没有“short cut”的普通神经网络和ResNet网络训练误差曲线对比如下:

ResNet对于中间的激活函数来说,有助于能够达到更深的网络,解决梯度消失和梯度爆炸的问题。

5,Inception Net

如果说ResNet 是为了更深,那么 Inception 家族就是为了更宽。

在构造卷积层时,卷积核的大小对结果有非常重要的影响。Inception模块通过将不同大小的卷积核构成的网络并联起来,解决了卷积核大小的选择问题,让模型自动去选择适合的卷积核大小。

这种模型架构的信息密度更大了,这就带来了一个突出的问题:计算成本大大增加。不仅大型(比如5×5)卷积过滤器的固有计算成本高,并排堆叠多个不同的过滤器更会极大增加每一层的特征映射的数量。

为了减少数据维度,Inception模块使用 1×1 卷积来执行特征图的降维。

多个Inception模块的堆叠构成Inception Network,下面是GoogLeNet的结构,也叫做Inception v1。

Inception 很快就变成了一种具有决定性意义的模型架构。最新的版本 Inception v4 甚至将残差连接放进了每一个模组中,创造出了一种 Inception-ResNet 混合结构。但更重要的是,Inception 展现了经过良好设计的「网中有网」架构的能力,让神经网络的表征能力又更上了一层楼。

Xception将Inception的思想推向了极致。它的假设是:跨通道的相关性和空间相关性是完全可分离的,最好不要联合映射它们。

在 Inception 中,我们使用 1×1 的卷积将原始输入投射到多个分开的更小的输入空间,而且对于其中的每个输入空间,我们都使用一种不同类型的过滤器来对这些数据的更小的 3D 模块执行变换。Xception 更进一步。不再只是将输入数据分割成几个压缩的数据块,而是为每个输入通道单独映射空间相关性,然后再执行 1×1 的深度方面的卷积来获取跨通道的相关性。

6,迁移学习

在我们实施自己的工作的时候,比如说做某种物体的识别分类,有时候只有少量的数据集,对于从头开始训练一个深度网络结构是远远不够的。

但是我们可以应用迁移学习,应用其他研究者建立的模型和参数,用少量的数据仅训练最后自定义的softmax网络。从而能够在小数据集上达到很好的效果。

如果我们有更多的数据,我们可以解冻后面的一些层,以获得更好的训练效果。

人脸识别

1,人脸识别和人脸验证

人脸验证(Face Vertification):

  • 输入两张人的图片;
  • 输出这两张图片是否是同一个人。

人脸识别(Face Recognition):

  • 拥有一个具有K个人的数据库;
  • 输入一副人脸图片;
  • 如果图片是任意这K个人中的一位,则输出对应人的ID。

人脸识别问题对于人脸验证问题来说,具有更高的难度。例如对于一个验证系统来说,如果我们有99%的正确率,那么这个验证系统已经具有了很高的精度;但是假设在另外一个识别系统中,如果我们把这个验证系统应用在具有K个人的识别系统中,那么系统犯错误的机会就变成了K倍。

人脸识别问题具有一个很困难的地方就是这是一个 one shot learning问题。我们需要仅仅通过先前的一张人脸的图片或者说一个人脸的样例,就能够实现该人的识别。对于one shot learning 问题,因为只有单个样本,是不足以训练一个稳健的卷积神经网络来进行不同人的识别过程。而且,在有新的样本成员加入的时候,往往还需要对网络进行重新训练。所以我们不能以传统的方法来实现识别系统。

因此我们只能将其转换为一个人脸验证问题来进行解决。

2,学习 Similarity 函数

为了能够让人脸识别系统实现一次学习,需要让神经网络学习 similarity 函数 d(img1,img2)。

d(img1,img2) 表示两幅图片的差异度。如果d(img1, img2) > delta,则输出same, 否则输出 different。

对于人脸识别系统,通过将输入的人脸图片与数据库中所拥有的图片成对输入Similarity函数,两两对比,则可解决one shot problem。如果有新的人加入团队,则只需将其图片添加至数据库即可。

我们可以利用Siamese 网络来实现 Similarity 函数。

对于一个卷积神经网络结构,我们去掉最后的softmax层,将图片样本1输入网络,最后由网络输出一个N维的向量(图中实例以128表示),这N维向量则代表输入图片样本1的编码。将不同人的图片样本输入相同参数的网络结构,得到各自相应的图片编码。

我们将Similarity 函数表示成两幅图片编码之差的范数:

d(img1,img2) = || f(img1) - f(img2) ||^2

3,Triplet损失

如何通过学习神经网络的参数,得到优质的人脸图片的编码?方法之一就是定义 Triplet 损失函数,并在其之上运用梯度下降。

Triplet 损失函数的定义基于三张图片:Anchor、Positive、Negative。

整个网络的代价函数:

假设我们有一个10000张片的训练集,里面是1000个不同的人的照片样本。我们需要做的就是从这10000张训练集中抽取图片生成(A,P,N)的三元组,来训练我们的学习算法,并在Triplet 损失函数上进行梯度下降。为了更好地训练网络,我们需要选择那些训练有“难度”的三元组。

4,转换成二分类问题

除了利用 Triplet 损失函数来学习人脸识别卷积网络参数的方法外,我们还可以将这个验证问题转换成一个二分类问题,使用sigmoid激活单元来输出两张图片是否是同一个人的概率。

风格迁移

1,风格迁移

神经风格迁移可以从内容图片C和风格图片S,生成最终的风格迁移图片G,使得G的内容和C接近,而风格和S相似。

为了实现神经风格迁移,我们需要定义关于G的损失函数J,以用来评判生成图片的好坏。

损失函数为内容损失和风格损失之和。

通过随机初始化生成图片G,并执行梯度下降调整G的取值使得损失函数最小,最终可以得到内容和C接近,而风格和S相似的图片。

2,内容损失

我们可以使用一个预训练的卷积神经网络来定义内容损失,例如VGG-16。让内容图片和风格图片都对VGG-16的某个中间隐藏层做卷积运算,分别得到两个输出激活,这两个输出矩阵的差的范数可以用来衡量内容损失。

3,风格损失

我们定义图片的风格为图片通过卷积层后不同通道之间的相关性。可以定义如下风格矩阵。

风格损失可以定义为G和S之间风格矩阵的差的范数。

如果对各层都使用风格损失,那么效果会更好。

目标检测

1,目标检测问题

目标检测问题是非常困难的CV问题,也是自动驾驶中非常重要的技术模块。

目标检测问题可以分成目标识别和目标标注。目标识别相对容易,但是目标标注相对困难。如果图片中有多个目标需要识别和标注时,将变得尤其的困难。

2,目标定位方法

为了实现目标的定位,我们可以在标注目标是否存在的同时标注目标的边界框 boudary box,并进行训练。

3,同时检测多个目标

为了在一张图片中同时检测多个目标,我们一般可以使用滑动窗口的方法,在一个一个的小窗口中分别运行算法检测是否包含特定目标,然后将滑动窗口变大,在更大的一个一个的窗口中分别运行算法检测是否包含特定目标。

这种直接使用滑动窗口的方法有一个很大的缺点,那就是计算成本巨大。因为要反复运行算法非常多次,而实际上不同的滑动窗口有许多重合的位置,因此导致了许多的重复运算。

利用卷积运算,我们可以一次运算,检测多个滑动窗口中是否包含目标。或者说,我们可以利用卷积运算实现滑动窗口。

首先,CNN的全连接层可以用全局卷积和1*1的卷积代替。

在我们实现了以卷积层替代全部的全连接层以后,就可以在该基础上进行滑动窗口在卷积层上的操作。

卷积层实现滑动窗口的这个过程,我们不需要把输入图片分割成若干个子集分别执行前向传播,而是把它们作为一张图片输入到卷积神经网络中进行计算,其中的重叠部分(公共区域)可以共享大量的计算。

4,YOLO算法

把以上各种想法结合起来,我们可以构造YOLO算法。YOLO表示:You Only Look Once。也就是只要一次前向计算实现多个目标的识别和定位。

YOLO算法把图片分割成n×n个格子,每个格子的对应输出只关联中心落在其中的目标。

5,过滤同一个物体的多次检测

YOLO算法的不同格子会有大量的输出,有些格子的输出可能对应的是同一个物体,因此我们需要对这些输出进行过滤,以保留同一个物体的多个输出中概率最大的这个。这需要用到所谓的NMS算法,即非极大值抑制算法(Non-Maximum Suppression)。

使用NMS的方法一方面是过滤掉概率低于某个阈值的目标,另一方面是需要过滤掉目标位置重合度很高的一些目标,因为位置重合度很高意味着它们很可能是同一个物体。那么如何衡量位置重合度是否高呢?一般可以使用IOU指标(Intersection Over Union),即交并比。

6,检测同一个格子出现的多个目标

如果有两个目标同时出现在一个格子中,那么我们前面的算法显然不能同时将它们标注出来。

解决这个问题的一个思路是在一个格子上可以同时标注多个目标,那么如果有两个物体出现在这个格子中,例如图片中有一个行人和一个汽车,那么训练的label中是先标注行人还是汽车呢?

我们可以应用 anchor box 来解决这个问题。给每个格子设定多个anchor box,anchor box 具有一定的形状,目标和哪个anchor box 的IOU高,就把目标标注在哪个 anchor box对应的位置。

通过统计我们可以设定较为合理的不同的anchor box, 例如设定一个高瘦的anchor box 和一个长宽的 anchor box, 前者可以很容易地和行人匹配,后者可以很容易地和汽车匹配,从而解决同时标注多个目标的问题。

但是如果我们只设置了2个 anchor box,在某张图片中的同一个格子中又同时出现了3个对象,这时候我们依然难以正确的标注。当然,这种情况出现的概率很低,对模型的性能影响可以忽略。

0 人点赞