DeepLearning.ai笔记:(4-4)-- 特殊应用:人脸识别和神经风格转换

本周讲了CNN的两个特殊应用:人脸识别和神经风格转换。

人脸识别

Face Verification and Face Recognition

人脸识别和人脸验证不一样。

人脸验证是输入一张图片,和这个人的ID或者名字,然后根据输入的图片判断这个人是不是对应这个ID,是个1对1的问题。

人脸识别是有K个人的数据库,然后输入一张人脸的图片,不确定他是哪一位,然后输出在K个人的数据库中对应的那个人,是1对K的问题。

所以人脸识别难度更高,而且精度要求更高,因为如果每张图片都是99%的精度,那么K个人就是K倍了,所以应该有99.9%以上的精度。

One shot learning

人脸识别系统,通常都是只有一个人脸的样例,然后就能够成功的识别是不是这个人。这就是one shot learning,一次学习,单单通过一张照片就能识别这个人。

因此,在只有单个样本的情况下,并不能用之前的方法来实现这个识别系统。这里就需要有一个相似性函数。

similarity函数:

通过$d(img1,img2)$来表示两张图片的差异程度,如果d大于某个阈值,那么就表示差别很大,如果小于某个阈值,则认为是同一个人。

Siamese网络

那么如何计算这个$d(img1,img2)$呢?

可以利用Siamese网络来实现。

如图,输入两张图片$x^{(1)},x^{(2)}$,经过一个卷积神经网络,去掉最后的softmax层,可以得到N维的向量,$f(x^{(1)}),f(x^{(2)})$,假设是128维,而N维的向量就相当于是对输入图片的的编码(encoding)。

然后比较这两个向量之间的差值:

$$d(x1,x2) = ||f(x1) - f(x2)||^{2}_{2}$$

如果距离$d$很小,那表示这两张图片很相近,认为是同一个人。

如果距离$d$很大,那么表示这两张图片差别很大,不是同一个人。

Triplet loss

那么,我们之前说到,要得到输入图片的向量编码$f(x)$,是需要经过卷积神经网络的,那么卷积神经网络的参数如何确定呢?使用的方法就是Triplet loss损失函数,而后用梯度下降法进行迭代。

我们需要比较两组成对的图像 (Anchor, Positive, Negative),简写(A,P,N)

Anchor:表示要检测的目标图片

Positive:表示与anchor同个人的图片

Negative:表示与anchor不同个人的图片

所以我们希望A和P的距离小,A和N的距离大,因此有了如下不等式:

$$||f(A) - f(P)||^2 - ||f(A) - f(N)||^2 + \alpha \leq 0$$

这里这个公式与SVM的损失函数很类似,$\alpha$是表示margin边界,也就是增加$d(A,P)$和$d(A,N)$之间的差距。

而如果上面的不等式小于0,那说明是符合我们的要求的,如果是大于0,则要计入损失函数中,所以得到了Triplet loss的公式是:

$$L(A,P,N) = max(||f(A) - f(P)||^2 - ||f(A) - f(N)||^2 + \alpha,0)$$

整个网络的代价函数就是把所有的图片损失加起来:

$$J = \sum L(A,P,N)$$

三元组的选择

每个三元组的选择是有讲究的,如果你要识别的是一个女人,然后对比的Negative是个老大爷,那么条件就很容易满足,学不到什么东西。所以应该尽量选择那些相似的图片进行每一组的训练,也就是:

$$d(A,P) \approx d(A,N) $$

选择的例子如下图,可以看到,每一个三元组对比的都是一些比较相似的图片:

脸部验证和二分类

除了之前说的用Triplet loss进行训练以外,还有别的方法来进行训练,也就是可以把Siamese网络当做一个二分类的问题。

如图,输入两张图片,当计算得到了两个图片的向量编码后,求两张图片的距离,然后通过一个sigmoid函数,把他变成一个二分类问题,如果同个人,输出1,不同个人则输出0。其中,权重$W,b$都可以通过训练来得到。

这个时候,人脸识别问题就变成了一个监督学习的问题,在创建每一对训练集的时候,应该有对应的输出标签y。

神经风格迁移

神经风格的迁移,就是输入两张图片,一张当做内容图片content,另一张当做风格图片style,输出的图片g兼具有一张的内容,和另一张的风格。

卷积神经网络学什么?

在进行风格迁移前,我们需要了解我们的神经网络到底在学些什么东西,把中间的隐藏单元拎出来看看。

如上图,假设我们有一个卷积神经网络,要看到不同层的隐藏单元计算结果,怎么办?依次对各个层进行如下操作:

  • 在当前层挑选一个隐藏单元;
  • 遍历训练集,找到最大化地激活了该运算单元的图片或者图片块;
  • 对该层的其他运算单元执行操作。

对于在第一层的隐藏单元中,其只能看到卷积网络的小部分内容,也就是最后我们找到的那些最大化激活第一层隐层单元的是一些小的图片块。我们可以理解为第一层的神经单元通常会寻找一些简单的特征,如边缘或者颜色阴影等。

而后随着层数的增加,隐藏层单元看到的东西就越来越复杂了:

代价函数

对于神经风格迁移,我们的目标是由内容图片C和风格图片S,生成最终的风格迁移图片G。所以定义代价函数为:

$$J(G) = \alpha J_{content}(C,G) + \beta J_{style}(S,G)$$

  • $J_{content}(C, G)$: 代表生成图片G的内容和内容图片C的内容的相似度
  • $J_{style}(S, G)$: 代表生成图片G的内容和风格图片S的内容的相似度
  • $\alpha, \beta$: 两个超参数用来表示以上两者之间的权重

首先随机初始化G的像素,然后进行梯度下降:

内容代价函数

  • 首先假设我们使用第$l$层隐藏层来计算$J_{content}(C, G)$注意这里的$l$一般取在中间层,而不是最前面的层,或者最后层。因为太浅了啥也看不到,太深了就太像原图了。
  • 使用一个预训练的卷积网络。(如,VGG或其他)
  • $a^{[l] (C)}$和$a^{[l] (G)}$分别代表内容图片C和生成图片G的$l$层的激活值;
  • 内容损失函数$J_{content} = \frac{1}{2}||a^{[l] (C)} - a^{[l] (G)}||^2$

风格代价函数

对于一个卷积网络中,我们选择网络的中间层$l$, 定义“Style”表示$l$层的各个通道激活项之间的相关性。

那如何计算这个相关性呢?

假设我们在第$l$层有5个通道:

不同的通道之间代表着不同的神经元学习到的特征,如第一个通道(红色)可以表示含有垂直纹理的特征,第二个通道(黄色)表示区域中出现橙色的特征。

那么两个通道的相关性就表示图片中出现垂直纹理又出现橙色的可能性大小。

所以可以得到相关系数的矩阵“Gram Matrix

$i,j.k$表示神经元所在的高度,宽度和通道。也就是每个通道的神经元分别乘上另一个通道对应位置的神经元再求和即可得到这两个通道$k,k^{\prime}$的相关系数。这个矩阵的维度是$(n_{c}^{[l]},n_{c}^{[l]})$的,也就是第$l$层的通道数乘通道数的大小。

而代价函数即为两张图片中相关系数矩阵的差值求和,再取平均。

1D to 3D 卷积

图片都是2D的卷积运算,其实还可以推广到1D和3D的情况。

典型的1D情况就是信号处理。

3D情况就像CT的切片,是一层一层叠加起来的。

分享到