一:前言
Triplet Network最常用于人脸识别的领域,利用Triplet loss来学习人脸的特征向量表示。在看本文章之前,建议先观看Andrew Ng在Coursera上的deep learning specialization的相关课程。b站链接点这里。
1、介绍
triplet network的网络结构如他的名字,输入是一个三元组<a,p,n>
a(anchor): 正样本
p(positive ):与a是同一类别的样本,可以理解为也是正样本
n(negative):与a不是同一类别的样本,负样本
如上图所示,triplet network的输入是一个三元组,实际上是三个输入共享一个同网络的参数,分别输出三个图片的特征,然后进行d(a,p)以及d(a,n)的对比。d(a,p)为anchor与positive example的距离,此距离为类内距离,越小越好;d(a,n)为negative example 与anchor距离,此距离为类间距离,越大越好。
2、我们对这个模型的预期是什么?
模型本身作为一个encoding function,我们需要更新参数直到模型达到以下条件:
1.代表同一个人脸的两张图encoding出来的vector距离比较小,而代表不同人脸的两张图encoding出来的vector比较大。用公式表示为 :
但是,为了避免模型将f(img)学习成f(img)=0 来满足条件,我们引入了一个margin,将上述公式改成:
设定margin为一个常量,可以迫使模型努力学习出来能让两张不同图片的distance值更大,或者将两张相同的图片的distance更小。这里用吴恩达老师举的例子解释一下:
若我们不加margin参数,当计算出来的d(a,p)=0.5时,这时候d(a,n)=0.51也能满足条件,此时,网络对正负样本的区分能力不大。当我们添加了一个margin值为0.2时,计算出来d(a,p)=0.5的时候,这时候d(a,n)必须大于0.7才能满足条件,此时正负样本得到更好的区分。
3.如何将上述内容转化成损失函数?
作者将损失函数定义为:
L=max(d(a,p)−d(a,n)+margin,0)
公式解析:d(a,p)−d(a,n)+margin这部分实际上就是这一条公式,
当d(a,p)−d(a,n)+margin<=0时,这时候我们的数据比较容易训练,一下子就能区分出来,此时损失值直接设置成0,不用继续训练,这时候的反向传播会肯定当前的parameters的值。
当d(a,p)−d(a,n)+margin>=0时,整个L保持为当前的值,这时候损失值>0,说明当前还不是最优的参数,需要继续优化,反向传播会否定和惩罚去更新当前的parameters。
这么一来,模型就能朝着我们希望的方向演变。
4.Triplet mining,如何选择训练数据?
将triplet(三元组)分为三类,
easy triplets(简单三元组): triplet对应的损失为0的三元组,形式化定义为:d(a,n)>d(a,p)+margin
hard triplets(困难三元组): negative example 与anchor距离小于anchor与positive example的距离,d(a,n)<d(a,p)
semi-hard triplets(一般三元组): negative example 与anchor距离大于anchor与positive example的距离,但还不至于使得loss为0,d(a,p)<d(a,n)<d(a,p)+margin
我们一般在训练的时候选择困难三元组或者一般三元组而不是随机选择的,即使保证A,P指向同一个人也不行。为什么呢?因为随机选择的图片能让d(a,n)的距离很容易就很大,大于d(a,p),这样模型基本不需要怎么学习就能达到这个条件。那么当遇到P,N很相似的图片时候,我们的模型就失去识别的能力,这就是我们为什么不能随机选择图片的原因。
那么我们应该如何去选择图片呢,选择的标准是什么?
标准:d(a,p)尽可能接近d(a,n)的值,也就是困难三元组或者一般三元组。这样一来数据不易满足损失函数,损失值不那么低,模型必须认真训练自己的参数,从而努力让d(a,n)的值尽可能变大,d(a,p)的值尽可能变小。
以上就是最近学习的triplet的一些理解,希望对你有帮助,如有错误,恳请指出一起交流~
相关论文:
《FaceNet A unified embedding for face recognition and clustering》
《DeepFace closing the gab to human level performance》