FaceNet的原理和源码地址

 

自己就着软件翻译勉强读了一遍FaceNet的论文(FaceNet: A Unified Embedding for Face Recognition and Clustering
),但是大概英文太差,读完之后有些还是云里雾里,因此看了别人的博客帮助理解。个人觉得https://blog.csdn.net/yangjf91/article/details/79217744翻译的比较不错,此外https://blog.csdn.net/zshluckydogs/article/details/86099193 这篇对于三元组的选取部分讲的很棒,使我理解更清晰。另外github上现在有了TensorFlow写的源码:https://github.com/davidsandberg/facenet,此外还有国人写的源码解读:https://github.com/boyliwensheng/understand_facenet

主体部分都是转载以上文章,但是有个问题一直没懂,可能是因为很基础的问题,所以大家都没谈这个问题,也希望有人能给我解释一下,那就是如何从CNN得到的特征取映射为128维特征,这个映射用的是什么样的函数?L2范数归一化之后如何embedding为128维特征的呢?

首先说一下什么是FaceNet,这是一种近欧式空间度量反映人脸相识度的映射方法,直接进行端对端学习一个从图像到欧式空间的编码方法,然后基于这个编码再做人脸识别、验证和聚类等。最终都是直接用L2距离表示人脸间的相似性,利用FaceNet将人脸变为128维特征后,人脸任务就发生改变:

  • 人脸验证 –> 两个embeddings间距离的阈值判断
  • 人脸识别 –> K-NN分类
  • 人脸检索 –> k-means等聚类技术

传统模型的问题 
  传统人脸识别需要先训练一个分类器,把网络某一层输出导入分类器获取识别信息,因此存在间接低效的缺点,即模型产生的特征泛化能力不高且维数达上千维。有的方法采用PCA降维,但PCA是一种线性变换方法,本身对高层神经网络的改善不大,甚至会影响网络的功能。
FaceNet的模型 
  FaceNet用一个完整的模型输出128维特征,使用Triplet loss,添加一个distance margin来保证同一身份的目标和不同身份的目标之间差距足够大,人脸缩略图没有使用2D、3D转换,但有比例和翻转变化。
  因此FaceNet可以直接输入人脸图像,即可得到特征向量,是一个end-to-end的系统,不需要人为添加额外的处理(即自身有很强泛化能力,对于光照、拍摄角度均可实现同一身份目标的高聚类低耦合)

FaceNet的具体设计

1、模型设计 

图中Batch即为输入的图像(更确切的说是三元组图像),中间deep architecture实现对三元组图像提取特征矩阵,然后通过L2范数进行归一化,然后embedding成128维特征,通过Triplet loss进行训练。(此处不清楚如何就变为了128维)

中间deep architecture用的也是卷积神经网络,但是经典的如VGG、GoogleNet等分类网络,在做人脸验证时要抽取fc_layer或者某一卷积层的featuremap作为人脸的特征然后做比对证明“你” 是“你”,非常的不直接不高效(特征较多),而facenet就没有这个问题。它最大的优点就是一步到位,直接通过量化两张人脸通过网络映射成的128D向量之间的距离作出诸如验证、识别等任务。同时省却了其他人脸识别算法中人脸对齐操作。

2、Triplet loss 

Triplet loss被作者认为更适合做人脸验证,但没有和其它损失函数进行具体比较,只是提了思路相似的文献14(损失函数是当两者相同距离越小越好,两者不同时距离越接近(甚至超过)m越好。):

 

看一下论文中的示意图 

实现方式:从训练数据中抽取 A 的40张人脸图,然后选取其中一张作为 anchor,在选取另一张作为 positive,从不是A的脸的图中选取一张作为 negative。显然,我们希望通过网络训练得到最终实现||anchor - positive|| < ||anchor - negative||

 用数学表示:

对于所有的三元组,都要满足 anchor 与 positive 的距离加上(where α is a margin that is enforced between positive and negative pairs,即正样本和负样本之间必须存在的一个距离下限)小于 anchor 与 negative 的距离。

所以,FaceNet的 loss function 就可以写成如下的形式:
 

注意后面有一个 “+” ,等同于 max(f(x), 0), 结合论文理解,
如果 f(x) < 0,则结果为0,说明当前三元组是正确无需调整的 (no loss)
如果 f(x) > 0,则说明不满足限制条件
符合 loss function 的定义。

 3、Triplet的选择 

(2)式是网络的loss-function,也就是我们需要求解的最优化项,但是在此之前有一个很棘手的问题,如何在大量的正样本和负样本中选择 positive 和 negative 。当然你可以选择除 anchor 之外的所有 positive 以及 negative 列出所有可能的三元组,这样做计算量过大并且模型的收敛速度极慢,注意到 loss-function,如果三元组之间的关系满足公式(1),那么值为0也就是其对损失函数没有贡献,换言之真正起到优化损失函数的三元组是不满足公式(1)的。因此对于同一类样本也即来自于同一个人的人脸图像中给定一个 anchor ,计算其与剩下的所有 positive 的欧式距离然后选择最大值,同时计算 anchor 与 negative 欧式距离的最小值,只需要这个最大值小于最小值那么对所有的 positive 均可以与 negative 区分开也即正确分类。这个 positive 也被称为 hard-positive,这个 negative 叫 hard-negative,这样的三元组是 hard-triplets,也只有这样的三元组可以提升模型的学习能力。

在整个训练集上计算上述的最大值和最小值可能会导致模型欠拟和,因为 hard-positive 和 hard-negative 中会包含大量错误标签和人脸信息极少的图像,这会导致训练得到的模型不可用。论文中提出了两种解决算法:

(1)训练网络之前把样本分成 N 份,分别计算每一份样本的最大值和最小值(anchor 与 positive 欧式距离最大值,与negative 欧式距离最小值,选出 hard-positive/negative,下文的最大值、最小值都是这个意思),然后依次用这些数据训练网络,比如从第一份数据开始,训练完成后保持模型的参数,然后这些参数作为第二份数据训练模型时的初始化参数,依次类推。

(2)在每一个 mini-batch 中选 hard-positive/negative 。需要设置合适的 batch size(1800)

方法(2)更高效,论文中也是用的该方法,在每个 mini-batch 中为每个 ID 保证有 40张 positive,同时加入随机 negative faces。有一点不同的是论文中不只是用了 hard-positive 还用到了所有可能的 anchor-positive 组合,这样做模型更稳定,并且在训练时更易收敛。类似的如果只用 hardest-negatives 导致模型过早的收敛到不理想的局部最优点并且极有可能得到一个不可用的模型:,为了解决这个问题论文采取了下面这种方式来挑选 negative。

 这种方式选出的 negative 是 semi-hard,相比较 positive 它们离 anchor 足够远,但是它们与 anchor 的欧式距离非常接近 anchor-positive 的欧式距离,这些 negatives 分布在先验 positive 与 negative 距离之中(Those negatives lie inside the margin α.)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值