本文是吴恩达深度学习第四课:卷积神经网络。本次课程将会告诉大家如何构造卷积神经网络并应用到图像数据上。从中你会学到如何构建一个卷积神经网络、如何应用卷积神经网络到图像识别和目标检测上、学习如何使用神经风格转换去生成艺术作品、能将这些算法应用到更广泛的图像应用上,比如2D、3D数据和视频。
第四课有以下四个部分,本文是第一部分。
首先要区分人脸识别与人脸验证。
给定输入图片、ID或名字,人脸验证系统做的是验证是否是这个人。做的是1:1的匹配,这种模式最常见的应用场景便是人脸解锁,终端设备只需将用户事先注册的照片与临场采集的照片做对比,判断是否为同一人,即可完成身份验证。
而人脸识别是1:K的。假设数据库中有K个人的图片,输入某个人的图片,输出这个人是否与数据库中的图片匹配或没有识别。
人脸识别所面临的一个挑战是需要解决一次学习问题(one-shot learning problem)。即在大多数人脸识别应用中需要通过单一图片取识别某个人。
大多数机器学习模型在只有一个样本进行训练的时候都表现不好。我们来看一个例子,
假设你要做一个人脸识别门禁系统,这里有四个员工。然后来了一个人,叫简
那么机器需要通过仅有的简的一张图片来识别出这个人就是简,从而打开门
相反,如果来了一个人,并不是数据库中的4个人之一,机器要知道无法识别。
所以One-shot 学习问题只能通过一个样本来进行学习,以便能够识别出一个人。
大多数人脸识别系统都需要解决这个问题,
这样训练集就很小,这种很小的训练集不足以去训练CNN模型。假设今天又有一个新员工加入了,那么将有5个员工需要识别,CNN模型的输出数也要加1,这需要修改CNN的网络结构,并且还需要重新训练。
所以为了得到更合理的结果,现在要做的是学习一个相似函数,
d
代表两张图片的不同程度。
通常可以设定一个阈值,只要小于这个值,就认为这两张图片代表的是同一个人,这样就可以应用于识别任务。
分别用数据库中的员工去与这张图片计算“不相似度”,越小说明越相似。通过函数d(img1,img2)
解决了one-shot问题。 如果有新员工加入,只需要把新员工的照片加入数据库,系统依然能正常工作。
现在的问题是如何得到这个函数d
呢
实现函数d
的一个方式是使用Siamese网络
假设有一个这样的卷积网络,输入图片 x ( 1 ) x^{(1)} x(1),然后通过一系列卷积、池化和全连接等操作最终得到这样的特征向量,我们之前学过的例子是将这个向量喂给softmax单元,得到判断的类别。 这里我们关注的是这个向量,假设它有128个维度,我们给这个向量一个名词,叫做 f ( x ( 1 ) ) f(x^{(1)}) f(x(1)),可以把它看成是输入图像的编码。
建立一个人脸识别系统的方法是,如果要比较两张图片的话,就是分别计算这两张图片的编码。
这里计算编码用到的是同一个网络。
接着就可以用这两个编码向量之间差的范数来表示这两张图片的距离。
这种就叫Siamese网络架构。那么要如何训练这个网络呢。这个卷积神经网络的参数定义了一个编码函数 f ( x i ) f(x^{i}) f(xi),所学习参数时,如果两个图片中是同一个人,那么两个编码的距离就要小:
改变这个网络中不同层的参数,就可以得到不同的编码输出,编码的距离也不一样。所以可以通过反向传播来学习参数,以满足上面两个条件。
那如何定义目标函数呢
要想通过学习神经网络的参数来得到一个好的编码,方法之一就是定义三元组(Triplet)损失函数,然后通过梯度下降法来训练。
为了应用三元组损失函数,需要比较成对的图像,比如下面这对图像。
你想要它们的编码差异小,因为这是同一个人(吴恩达夫人)。
假如是上面这组图片,你想要它们的编码差异大一些,因为是不同的人(难道是吴恩达夫人与丈母娘)。
用三元组损失的术语来说,你要做的通常是看一个anchor图片,让anchor图片和positive图片(意味着同一人)的距离很近。
而当anchor图片和Negative(不同的人)图片的距离很远。这就是为什么叫三元组损失,因为需要同时看三张图片(anchor(A)、positive§和negative(N))。
通过公式表述的话,想要网络的参数(或得到的编码)满足一下特征:
不能要这些输出完全等于零,我们增加了一个超参数 α \alpha α,这样如果 f f f输出都为零的话就不满足了。这个 α \alpha α叫间隔(margin)。
下面就可以来定义损失函数了,给定3张图片 A , P , N A,P,N A,P,N:
这个 m a x max max的意思是,只要能使绿线的部分小于等于0,那么损失就是0;反之如果绿线部分大于0,那么损失就是大于零的这个值。
这是一个三元组定义的损失,整个网络的代价函数应该是训练集中的所有三元组损失之和:
为了定义三元组的数据集,你需要成对的 A A A和 P P P,所以你需要收集同一个人有多张照片的数据集。
那如何选择样本组成三元组呢,如果你随机的选择 A , P , N A,P,N A,P,N,要保证 A , P A,P A,P是同一个人, A , N A,N A,N是不同的人。
如果随机选择的话,那么这个约束条件很容易被满足,因为随机选择的图片, A A A和 N N N比 A A A和 P P P差别大的概率很大。
因此要尽可能选择很难训练的 A , P , N A,P,N A,P,N。
也就是选择的d(A,P)
要很接近与d(A,N)
。这样你的算法就会努力使左边的式子变小,右边的式子变大。这样这两个式子之间就会至少有一个 α \alpha α间隔。
在你得到了这样的数据集后
还需要做的是用梯度下降来最小化代价函数 J J J。
Triplet损失是学习人脸识别卷积网络参数的好方法,这节我们介绍一下其他的方法。
我们看看如何将人脸识别当成一个二分类问题。
另一个训练神经网络的方法是选取一个Siamese网络(上面其实是同一个网络,只是表示不同输入下的输出),使其同时计算这些特征向量。
然后将这些向量输入到逻辑回归单元,来预测是否为相同的人。
这样就转换为一个二分类问题。可以用这种方法来替换triplet损失的方法。
那最后的逻辑单元是如何处理的,输出的 y ^ \hat y y^为
这里的下标 k k k表示特征向量的维度。这里假设有128维。这是将这两个向量取元素差的绝对值。
这里有一个技巧,
假设这两张图片中有一张是数据库中的图片,我们不需要每次都重复将数据库中的图片喂给这个神经网得到编码,我们只需要计算一次,保存起来即可。 即我们只需要储存原始图像对应的特征向量。
这样可以节省大量的计算,每次只要计算想要识别图像的编码即可。
总结一下,把人脸验证当成一个监督学习问题,只要创建一个成对图片的训练集。
然后使用反向传播算法去训练Siamese神经网络。
神经风格转换可以完成这件事情。为了更好的描述,这里用 C C C表示内容(Content)图像, S S S表示风格(Style)图像, G G G表示生成(Generate)的图像。
为了实现神经风格转换,你需要使用卷积网络提取特征。
深度卷积网络到底在学什么,本节通过一些可视化的例子来帮助大家了解。
这有助于理解如何实现神经风格迁移。
假设你训练了一个网络,你希望看到不同层之间隐藏单元的计算结果。
你可以这样做,从第一层的某个隐藏单元开始,假设你遍历了训练集,发现一些图片或图片块,能最大程度的激活这个单元。
注意到一个特定的单元只能看到图片中的一小部分,因此下面只画出了一小块:
如果你选择了一个隐藏单元,要找出哪9个输入图像块最大程度的激活了这个单元。你可能找到了上面这样的9个图像块。
可以看到这个单元是在进行边缘检测,寻找上图这9种边缘。
然后可以选择零一个隐藏单元,重复进行上面的步骤。
把第二个隐藏单元关心的图像块加到右边,它寻找的边缘线条看起来和第一个的倾斜程度是不同的。
现在我们得到了第一层网络中某些隐藏单元的结果,那如何对剩下的所有深层的某些单元做这样的操作会得到什么呢。
在更深的层中隐藏单元将看到更大一部分图像,
这是第一层和第二层中某9个单元得到的结果,
左上角这9个格子里面是让一个隐藏单元高度激活的九个图块,上面这个图片展示了第2层的9个隐藏单元激活的图块。
对于更深层可以重复这个过程
我们分别放大这些图片,下面是第二层:
看起来第2层在检测更加复杂的形状和模式,有寻找垂直纹理的,有寻找圆形的,还有寻找非常细的直线的。
那第3层呢
第三层就更加复杂,有的单元对汽车轮子比较感兴趣,有的对人物上半身比较感兴趣。
那下一层呢
第4层看起来比第3层还要复杂,左上角的9个格子好像说的是这个单元已经实现了一个狗检测器了。
我们经历了很长的过程从检测相对简单的东西到复杂的物体,比如从第1层的边到第2层的纹理,再到更深层中检测的非常复杂的物体。
要构建一个神经风格转换系统,需要定义一个生成图像的代价函数,来判断生成图像的好坏。
那么怎么判断生成图像的好坏呢,我们把这个函数定义为两部分。第一部分称为内容代价,用来度量生成的图片和内容图片 C C C有多相似。第二部分是风格代价函数,用来度量图片 G G G的风格和图片 S S S有多相似。 最后用两个超参数来确定两部分之间的权重。
为了生成一个新图像,接下来要做的是,
随机初始化生成图像 G G G
使用梯度下降法来最小化 J ( G ) J(G) J(G) ,这一步实际上更新的是图像的像素值。
举个例子,这里是想要转换的图片和艺术图片。
假设第一步随机生成的是这种像素点:
接下来运行梯度下降法最小化代价函数 J J J,逐步处理相似度,慢慢得到下面这样一个图片:
最后用越来越像的风格画出下面的图片
下面我们来看下如何定义内容代价函数。
我们整个代价函数是这样的,我们来看下内容代价函数是如何定义的。
假设你用隐藏层 l l l来计算内容代价,如果 l l l很小,比如用隐藏层 1 1 1,这样这个代价函数就会使你的生成图片,像素上非常接近于你的内容图片;如果用很深的层,如我们之前看到的,可能会变成判断内容图片中是否含有狗。这样它就会生成一个狗的图片。
在实际中,我们不会选的太深,也不会选的太浅,通常会选网络的中间层。
假设使用的是一个预训练的卷积模型。
现在你需要衡量一个内容图片和一个生成图片它们在内容上的相似度。
用 a [ l ] ( C ) a^{[l](C)} a[l](C)和 a [ l ] ( G ) a^{[l](G)} a[l](G)分别表示这两个图像 l l l层的激活值。
如果这两个激活值很接近,那么就认为这两张图像在内容上也很接近。
所以可以这样定义内容损失函数:
这是按元素将这两个激活值的差异平方进行求和。
所以之后你对 J ( G ) J(G) J(G)使用梯度下降法来求 G G G,这样使这个算法找到一个图像 G G G使得这些隐藏层的激活值和你的内容图像比较接近。
下面我们来看看风格代价函数的定义。
图片的风格是什么意思呢
假设你使用第 l l l层的激活值来衡量风格。
我们要做的是将风格定义为层中不同激活通道之间的相关系数,假设选择了激活层 l l l,它的激活矩阵是这样的。
我们想知道的是不同的激活通道间的相关性有多大,在这个激活矩阵上,我们用不同的颜色来表示不同的通道。
假设我们有5个通道,我们先看下前两个通道,即红色和黄色通道,看这两个激活通道的相关性多大,
具体的做法是遍历这两个通道对应位置的激活值,组成一些成对的数。然后看当你遍历所有这些位置,这些成对的数之间的相关性有多大。那为什么这能表示风格呢
假设红色通道对应于上图红线框出的9个图像块,而黄色通道对应于黄线框出的9个图像块。
相关系数描述的是当图片某处出现红线框出的这种垂直纹理时,改处同时又是橙色的可能性。
如果我们在通道之间使用相关系数来描述通道的风格,你能做的就是测量你的生成图像中,第一个通道是否与第二个通道有关,
通过测量,你能知道在生成的图像中,垂直纹理和橙色同时或不同时出现的频率。这样就能测量生成图像的风格和输入的风格图像的相似程度。
对于也就是风格图像和生成图像,你需要计算一个风格矩阵,就是用 l l l层来测量风格。
接着我们定义风格图像,设这个关于 l l l层的风格图像 G G G如下
这里的 k k k和 k ′ k^{\prime} k′表示同一位置不同通道。然后再对生成图像做同样的定义
现在要做的就是计算出这张图像的风格矩阵,以便能测量出刚才所说的这些相关系数。
最后我们将 S S S和 G G G的损失函数定义为,
上图看不清楚可以看下面这个图片:
这就是对 l l l层定义的风格代价函数。
如果你对各层都使用风格代价函数,会让结果变得更好。
比如上图左边是一个心电图,每个峰值与心跳相一致 ,比如你想要用心电图去做医学诊断,你会有一维的数据。如上面心电图下方的数字所示,这是一个按照时间顺序显示每次电压的序列。
这种情况下需要与5维的过滤器进行卷积,而不是 5 × 5 5 \times 5 5×5的过滤器。
在一维过滤器中,需要用到你的5维过滤器,应用到这维信号的每个不同位置。
那3维数据是怎样的呢,假设接受CT扫描,它可以得到你身体的三维模型的X光扫描。
可以得到人体躯干的不同切面
所以3维数据通常除了高度和宽度外还有一个深度:
注意3维图像中还是会有一个通道数的,这里假设是黑白图片,所以通道数为1。
另一个可以作为3维数据的例子是视频数据,不同的帧在视频中是按时间顺序排列的。你可以用来检测视频中人的运动。