吴恩达Coursera深度学习课程 DeepLearning.ai 编程作业(4-4)----------
作者: 大树先生
博客: http://blog.csdn.net/koala_tree
知乎:https://www.zhihu.com/people/dashuxiansheng
GitHub:https://github.com/KoalaTree
2017 年 11 月 27日
Ng卷积神经网络部分,完结撒花!以下为在Coursera上吴恩达老师的 DeepLearning.ai 课程项目中,第四部分《卷积神经网络》第四周课程“特殊应用:人脸识别和神经风格迁移”关键点的笔记。本次笔记几乎涵盖了所有视频课程的内容。在阅读以下笔记的同时,强烈建议学习吴恩达老师的视频课程,视频请至 Coursera 或者 网易云课堂。
同时我在知乎上开设了关于机器学习深度学习的专栏收录下面的笔记,以方便大家在移动端的学习。欢迎关注我的知乎:大树先生。一起学习一起进步呀!_
卷积神经网络 — 特殊应用:人脸识别和神经风格迁移
Part 1:人脸识别
1. 人脸验证和人脸识别
人脸验证(Verification):
- Input:图片、名字/ID;
- Output:输入的图片是否是对应的人。
- 1 to 1 问题。
人脸识别(Recognition):
- 拥有一个具有K个人的数据库;
- 输入一副人脸图片;
- 如果图片是任意这K个人中的一位,则输出对应人的ID。
人脸识别问题对于人脸验证问题来说,具有更高的难度。如对于一个验证系统来说,如果我们拥有 99 % 99\% 99%的精确度,那么这个验证系统已经具有了很高的精度;但是假设在另外一个识别系统中,如果我们把这个验证系统应用在具有K个人的识别系统中,那么系统犯错误的机会就变成了K倍。所以如果我们想在识别系统中得到更高的精度,那么就需要得到一个具有更高精度的验证系统。
2. one shot learning
对于大多数的人脸识别系统都存在的一个问题就是one shot learning。
什么是one shot learning:
对于一个人脸识别系统,我们需要仅仅通过先前的一张人脸的图片或者说一个人脸的样例,就能够实现该人的识别,那么这样的问题就是one shot 问题。对于存在于数据库中的人脸图片,系统能够识别到对应的人;而不在数据库中的人脸图片,则系统给出无法通过识别的结果。
对于one shot learning 问题,因为只有单个样本,是不足以训练一个稳健的卷积神经网络来进行不同人的识别过程。而且,在有新的样本成员加入的时候,往往还需要对网络进行重新训练。所以我们不能以传统的方法来实现识别系统。
Similarity 函数:
为了能够让人脸识别系统实现一次学习,需要让神经网络学习 Similarity 函数:
- d(img1, img2):两幅图片之间的差异度
- 输入:两幅图片
- 输出:两者之间的差异度
- 如果 d ( i m g 1 , i m g 2 ) ⩽ τ d(img1, img2) \leqslant \tau d(img1,img2)⩽τ,则输出“same”;
如果 d ( i m g 1 , i m g 2 ) > τ d(img1, img2) > \tau d(img1,img2)>τ,则输出“different”.
对于人脸识别系统,通过将输入的人脸图片与数据库中所拥有的图片成对输入Similarity函数,两两对比,则可解决one shot problem。如果有新的人加入团队,则只需将其图片添加至数据库即可。
3. Siamese 网络
利用Siamese 网络来实现 Similarity 函数。
构建网络:
对于一个卷积神经网络结构,我们去掉最后的softmax层,将图片样本1输入网络,最后由网络输出一个N维的向量(图中实例以128表示),这N维向量则代表输入图片样本1的编码。将不同人的图片样本输入相同参数的网络结构,得到各自相应的图片编码。
Similarity 函数实现:
将Similarity 函数表示成两幅图片编码之差的范数:
d ( x 1 , x 2 ) = ∣ ∣ f ( x 1 ) − f ( x 2 ) ∣ ∣ 2 2 d(x1, x2) = ||f(x1)-f(x2)||_{2}^{2} d(x1,x2)=∣∣f(x1)−f(x2)∣∣22
那么也就是说:
- 我们的神经网络的参数定义了图片的编码;
- 学习网络的参数,使我们得到好的Similarity 函数:
- 如果 x 1 , x 2 x_{1},x_{2} x1,x2是同一个人的图片,那么得到的 ∣ ∣ f ( x 1 ) − f ( x 2 ) ∣ ∣ 2 ||f(x1)-f(x2)||^{2} ∣∣f(x1)−f(x2)∣∣2很小;
- 如果 x 1 , x 2 x_{1},x_{2} x1,x2不是同一个人的图片,那么得到的 ∣ ∣ f ( x 1 ) − f ( x 2 ) ∣ ∣ 2 ||f(x1)-f(x2)||^{2} ∣∣f(x1)−f(x2)∣∣2很大。
4. Triplet 损失
如何通过学习神经网络的参数,得到优质的人脸图片的编码?方法之一就是定义 Triplet 损失函数,并在其之上运用梯度下降。
学习目标:
为了使用Triplet 损失函数,我们需要比较成对的图像(三元组术语):
- Anchor (A): 目标图片;
- Positive(P):与Anchor 属于同一个人的图片;
- Negative(N):与Anchor不属于同一个人的图片。
对于Anchor 和 Positive,我们希望二者编码的差异小一些;对于Anchor 和Negative,我们希望他们编码的差异大一些。所以我们的目标以编码差的范数来表示为:
d ( A , P ) = ∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 ⩽ ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 = d ( A , N ) d(A,P)=||f(A) - f(P)||^{2} \leqslant ||f(A) - f(N)||^{2} = d(A,N) d(A,P)=∣∣f(A)−f(P)∣∣2⩽∣∣f(A)−f(N)∣∣2=d(A,N)
也就是:
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 ⩽ 0 ||f(A) - f(P)||^{2} - ||f(A) - f(N)||^{2} \leqslant 0 ∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣2⩽0
上面的公式存在一个问题就是,当 f ( A ) = f ( P ) = f ( N ) = 0 f(A)=f(P)=f(N)=0 f(A)=f(P)=f(N)=0时,也就是神经网络学习到的函数总是输出0时,或者 f ( A ) = f ( P ) = f ( N ) f(A)=f(P)=f(N) f(A)=f(P)=f(N)时,也满足上面的公式,但却不是我们想要的目标结果。所以为了防止出现这种情况,我们对上式进行修改,使得两者差要小于一个较小的负数:
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 ⩽ − α ||f(A) - f(P)||^{2} - ||f(A) - f(N)||^{2} \leqslant - \alpha ∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣<