特殊应用:人脸识别和神经风格迁移
1.人脸识别(Face Recognition)
人脸识别包括两个部分:
(1)验证(Verification)
输入图像,名字/ID;输出所输入的图像是不是所要验证的那个人。
(2)识别(Recognition)
l 拥有K个人的数据库。
l 得到一个输入图像。
l 如果输入图像是这K个人之一,输出ID;否则的话,输出“未识别”。
人脸识别问题相对于人脸验证来说具有更高难度。对于一个验证系统来说,如果拥有99%的精确度,则这个系统已经有很高的精确度;但是对于识别系统来说,99%的精确度远远不够,因为如果我们将验证系统应用在K个人的识别系统中,那么系统错误就变成了原来的K倍,这是非常可怕的。因此,在识别系统中我们的要求精确度更高。
1.1 单点学习(One-shot learning)
什么是单点学习呢?单点学习就是指仅仅通过先前的一张人脸的图片或者说一个人脸的样例,就能够实现该人的识别。因为实际上,对于应用系统来说,我们不可能搜集太多单个人的照片,这是不现实的。
因此,对于此种情况来说,我们不可能应用以前的学习方法来进行学习。所以在这里,我们采用的是学习相同度函数。
我们令d(img1, img2)=图片之间不同的程度,取一个合适的数τ。这样,如果d(img1, img2)≤τ时,我们可以认定这两张图片是同一张图片,;如果d(img1, img2)>τ,我们就认为它是不同的。这本质上是一个验证的过程。
这样,我们可以解决了单点问题。当然,如果有新的成员加入团队,则只需要将其照片添加到数据库就可以了。
1.2 Siamese网络(Siamese network)
注:本节内容来自:Taigman et. al., 2014. DeepFace closing the gap to human level performance
接下来,我们来用Siamese来构建相同度函数。
如图1所示,首先构建整个网络。对于一个卷积神经网络结构,我们去掉最后的softmax层,将图片样本1输入网络,最后由网络输出一个N维的向量(图中输出结果为128),这N维向量则代表输入图片样本1的编码。将不同人的图片样本输入相同参数的网络结构,得到各自相应的图片编码。
图1
这里的相同度函数定义为一个2-范数的平方:
d(x1, x2)=||f(x1)-f(x2)||22
总结:
1. 我们用神经网络的参数定义了图片的编码;
2.我们通过学习参数,可以来计算我们的相同度函数:如果是同一个人,那么d(x1, x2)很小;如果不是同一个人,那么d(x1, x2)很大。
1.3 三元组损失函数(Triplet loss)
注:本节内容来自:Schroff et al.,2015, FaceNet: A unified embedding for face recognition and clustering
要使用神经网络学习参数,得到良好的人脸图片的编码,需要定义损失函数,这里我们定义的是三元组损失函数,然后运用梯度下降算法。
学习目标:
图2
对于图中,我们做出以下定义:
(1)Anchor(A):目标图片;
(2)Positive(P):与Anchor是同一个人的图片;
(3)Negative(N):与Anchor不同。
我们的目标是,A和P的编码差异应该小一些,A和N的编码差异大一些,所以我们采用了下面这个范数定义表示:
图3
上面的公式存在一个问题就是,当f(A)=f(P)=f(N)=0时,也就是神经网络学习到的函数总是输出0时,或者f(A)=f(P)=f(N)时,也满足上面的公式,但却不是我们想要的目标结果。所以为了防止出现这种情况,我们对上式进行修改,使得两者差要小于一个较小的负数:
图4
这里的“+α”被称为margin。不同margin值的设置对模型学习具有不同的效果,margin 的作用就是拉大了Anchor与Positive图片和Anchor与Negative图片之间的差距。
Triplet损失函数:
定义:
L(A,P,N)=max(||f(A)−f(P)||2−||f(A)−f(N)||2+α, 0)
则整个网络的代价函数为:
图5
假设我们有一个10000张片的训练集,里面是1000个不同的人的照片样本。我们需要做的就是从这10000张训练集中抽取图片生成(A,P,N)的三元组,来训练我们的学习算法,并在Triplet 损失函数上进行梯度下降。
注意:为了训练我们的网络,我们必须拥有Anchor和Positive对,所以这里我们必须有每个人的多张照片,而不能仅仅是一张照片,否则无法训练网络。
三元组(A,P,N)的选择:
在训练期间,如果A,P,N是随意选择,那么d(A, P)+α≤d(A, N)很容易被满足。所以,为了更好的训练网络我们需要选择那些更具有难度的来进行训练,也即d(A, P)≈d(A, N)的进行训练。
这样,我们的网络会使左侧d(A,N)+α变小,或者使得右侧d(A,N)变大;另外还会增加学习算法的计算效率,避免了那些简单的三元组。
1.4 面部验证和二分类(Face verification and binary classification)
除了利用 Triplet 损失函数来学习人脸识别卷积网络参数的方法外,还有其他的方式。我们可以将人脸识别问题利用Siamese网络当成一个二分类问题,同样可以实现参数的学习。
对两张图片应用Siamese 网络,计算得到两张图片的N维编码,然后将两个编码输入到一个logistic regression 单元中,然后进行预测。如果是相同的人,那么输出是1;如果是不同的人,输出是0。那么这里我们就将人脸识别的问题,转化为一个二分类问题。
图6
2. 神经风格迁移(Neural style transfer)
所谓神经风格迁移,就类似于我们之前用某个相机软件,将我们所拍的照片例如转换成毕加索画风格的这种操作。
2.1 深度网络学习内容可视化
本节内容来自:Zeiler and Fergus., 2013, Visualizing and understanding convolutional networks
图7
如果我们需要看到不同层隐藏单元的结算结果,我们应该对各个层这样做:
(1)在当前层挑选一个隐藏单元;
(2)遍历训练集,找到最大化地激活了该运算单元的图片或者图片块;
(3)对该层的其他运算单元执行操作。
对于在第一层的隐藏单元中,其只能看到卷积网络的小部分内容,也就是最后我们找到的那些最大化激活第一层隐层单元的是一些小的图片块。我们可以理解为第一层的神经单元通常会寻找一些简单的特征,如边缘或者颜色阴影等。
2.2 神经风格迁移代价函数
本节内容来自:
Gatys et al., 2015. A neural algorithm of artistic style. Images on slide generated by Justin Johnson
Gatys et al., 2015. A neural algorithm of artistic style
我们定义神经风格迁移的代价函数为:
其中,Jcontent(C,G)代表生成图片G的内容和内容图片C的内容的相似度;Jstyle(S,G) 代表生成图片G的内容和风格图片S的内容的相似度;α、β两个超参数用来表示以上两者之间的权重。
下面开始介绍总体执行过程:
1.找到生成图像G。首先是随机初始化G,产生一个白噪声图像,大小例如为100×100×3。
2.然后利用梯度下降算法来最小化J(G)。不断循环,一次次训练,最后得到风格迁移图片G。
接下来分别介绍内容代价函数Jcontent(C,G)和风格代价函数Jstyle(S,G):
1.内容代价函数:
假设我们使用隐藏层l来计算内容代价函数;
使用一个预训练的卷积网络(如VGG);
令a[l](C)和a[l](G)分别代表内容图片C和生成图片G的l层的激活值;
如果a[l](C)和a[l](G)相似,那么两张图片就有相似的内容。
2.风格代价函数
什么是一张图片的“Style”呢?
对于一个卷积网络中,我们选择网络的中间层l,定义“Style”表示l层的各个通道激活项之间的相关性。
如何衡量相关性呢?
图9
上面是我们选出的l层的激活项,对于不同的通道值,代表不同的神经元所学习到的特征,这里假如红色的通道可以找到图片中含有垂直纹理特征的区域,黄色通道可以找出橙色的区域。
而相关性大小的含义就是,如假设中,图片出现垂直纹理特征的区域显示橙色可能的大小。
我们将相关系数应用到风格图片S和生成图片G的对应通道上,就可以度量风格图片和生成图片的相似度。
Style 矩阵:
令a[l]i,j,k表示(i,j,k)位置的激活值,其中i,j,k分别代表激活值的高、宽、通道;
G[l]是一个第l层的nc×nc的矩阵:
图10
那么代价函数为:
内容代价函数和风格代价函数前面的归一化可以加也可以不加,因为总体的代价函数前面有权重系数。
如果对各层都使用风格代价函数,那么会让结果变得更好: