Facenet论文阅读笔记(包括GoogLenet参数计算方式)

来源:互联网 发布:追星 知乎 编辑:程序博客网 时间:2024/06/05 17:12

论文:FaceNet: A Unified Embedding for Face Recognition and Clustering(文章是2015年CVPR的文章)

1 统述

  • 功能:face verification (is this the same person)
    recognition (who is this person)
    clustering (find common people among these faces)

  • 人脸识别方向论文总结:
    一,识别精度超过0.95(超过人类的识别准确度)
    二,公布了方法(部分结果为商业公司提交,方法并未公布,比如Tencent-BestImage)
    三,使用深度学习方,近两年的结果。
    1,face++(0.9950 );2,DeepFace(0.9735 );3,FR+FCN(0.9645 );4,DeepID(0.9745 );5,FaceNet(0.9963 );6,baidu的方法(0.9977 );7,pose+shape+expression augmentation(0.9807);8,CNN-3DMM estimation(0.9235 ,准确率没那么高,但是值得参考)。
    https://zhuanlan.zhihu.com/p/24816781

Facenet一些特点:

  • 与其他的深度学习方法在人脸上的应用不同,FaceNet并没有用传统的softmax的方式去进行分类学习,然后抽取其中某一层作为特征,而是直接进行端对端学习一个从图像到欧式空间的编码方法(Euclidean embedding),然后基于这个编码在嵌入空间(embedding space)用(欧氏距离)L2 distance对比做人脸识别、人脸验证和人脸聚类等。FaceNet算法有如下要点:

  • 去掉了最后的softmax,而是用三元组计算距离的方式来进行模型的训练。使用这种方式学到的图像表示非常紧致,使用128位足矣。(特征向量的维度选择问题,维度约小计算越快,但是太小的话很难区分不同图片;维度越大越容易区分不同图片,但是太大训练模型不易收敛,且测试时计算慢,占用空间大。作者实验证明 128 维的特征能够较好的平衡这个问题)

  • 三元组的选择非常重要,选的好可以很快的收敛

用欧氏距离判断人脸是否相似的例子 :
这里写图片描述
如果是一个人的照片,他们的距离就会低于这个阀值,此处应该是1.1左右。这个有点类似于LDA的思想了。类内的距离就小,类间的距离就大,其实本质上并没有什么差别。

2 FaceNet总体架构

这里写图片描述
Deep Architecture就是卷积神经网络去掉softmax后的结构,经过L2的归一化(f(x)2=1所有图像的特征都会被映射到一个超球面上),然后得到特征表示,基于这个特征表示计算三元组损失(本文章最大特点提出triplet loss)。

目标函数(Triplet loss)

这里写图片描述
所谓的三元组就是三个样例,如(anchor, positive, negative),其中,a和p是同一类,a和n是不同类。那么学习的过程就是学到一种表示,对于尽可能多的三元组,使得anchor和positive的距离,小于anchor和negative的距离。
上面的思想用数学公式可以表示为
这里写图片描述
经过等价转换后可以得到Triplet loss函数
这里写图片描述

  • 这里距离用欧式距离度量,+表示[]内的值大于零的时候,取该值为损失,小于零的时候,损失为零。
  • 由目标函数可以看出:
    xaxn之间的距离小于xaxp之间的距离加α时,[ ]内的值大于零,就会产生损失。
    xaxn之间的距离 >= xaxp之间的距离加α时,损失为零。

triplet loss梯度推导

这里写图片描述
这里有一个小trick,因为导数的结果在上面的loss中已经计算了一些可以在编程时保存减少计算量

三元组的选取

首先最容易想到的从所有样本中找出离他最近的反例和离它最远的正例,然后进行优化。
缺点

  • 容易受不好的数据的主导
  • 导致得到的模型会陷入局部最优甚至崩溃。

所以,为了解决上述问题

在线生成triplet,在每一个mini-batch中选择hard pos/neg 样例(即MBGD方法不使用BGD与SGD方法)。

argmaxf(xai)f(xpi)2

argminf(xai)f(xni)2

1. 为了使mini-batch中生成的triplet合理,生成mini-batch的时候,保证每个mini-batch中每个人平均有40张图片。然后随机加一些反例进去。在生成triplet的时候,找出所有的anchor-pos对,然后对每个anchor-pos对找出其hard neg样本。这里,并不是严格的去找hard的anchor-pos对,找出所有的anchor-pos对训练的收敛速度也很快。
2. 除了上述策略外,还可能会选择一些semi-hard的样例,所谓的semi-hard即不考虑alpha因素,Batch size大约1800个样例40个正样例,下面所示为semi-hard条件:
这里写图片描述

3 深度网络架构(即2中Deep Architecture部分)

这个部分是可以更改的,本文主要讨论GoogLenet;在FaceNet文章中有两种网络结构:
1. ZFnet
2. GoogLenet (Inception结构将稀疏矩阵聚类为较为密集的子矩阵来提高计算性能而又不会产生太多的参数)

下面是GoogLenet的inception结构:这里写图片描述

Facenet应用的GoogLenet网络结构

FaceNet中应用的GoogLenet结构与原来的结构有一些不同
下图是GoogLenet的结构
这里写图片描述
下面是Facenet中GoogLenet结构图
这里写图片描述
下面讲解GoogLenet参数计算方式

  • 经过第一层conv1层(7*7*3),stride为2,padding为3(在这里是非对称padding所以才能输出112*112规格)
    第一层参数计算:7*7*3(卷积核)*64(特征数量)+64(偏置)=9472=9k
  • 第一层Flops计算(即乘法的次数)
    (7*7*3*64)*112*112=118816768=119M
  • 经过max(3*3,2)层,输出只与stride与padding有关,所以输出是56*56*64
  • 经过inception(2)层
    参数计算:(1*1*64)*64+(3*3*64)*192+192=114944=115k
    Flops计算 :
    (1*1*64*64)(参数量)*56*56(输出图片规格)+(3*3*64*192)(参数量)*56*56(输出图片规格)=360464384=360M
    计算Flops的想法:就是计算所有乘法的数量,就是卷积核的参数乘以特征数量再乘以图片的规格(大小)
  • 经过max(3*3,2):同上
  • 经过inception(3a):
    小tips(reduce是指经过1*1卷积核降维之后的特征数量再经过n*n卷积核计算)
    参数计算:(1*1*192*64)+64(经过1*1卷积核的参数)+(1*1*192*96)+96+(3*3*96*128)+128(经过1*1reduce之后再用3*3卷积核计算)+(1*1*192*16)+16+(5*5*16*32)(5*5卷积核)+1*1*192*32(经过max之后的1*1卷积)=163696=164k
  • 最后一层全连接(FC层):
    参数计算:1024*128=131072=131k
    计算如上所示,剩下的层数的参数都可以计算出来

4 实验结果

验证方法

D(xi,xj)是阈值(用L2距离)

Psame(相似图像对),Pdiff(相异图像对)
(True Accept)

TA(d)=(i,j)Psame,withD(xi,xj)d

(False Accept)
FA(d)=(i,j)Pdiff,withD(xi,xj)d

VAL(d)=|TA(d)||Psame|

FAR(d)=|FA(d)||Pdiff|

1. 不同的网络配置下的识别率

这里写图片描述

2. 不同的图像质量下的识别率

这里写图片描述

3. 不同的特征维度下的识别率

这里写图片描述

4. 不同的训练图像数据集的大小

这里写图片描述

5. 对齐的影响

在LFW上,使用了两种模式:
直接取LFW图片的中间部分进行训练,效果98.87%左右。
使用额外的人脸对齐工具,效果99.63%左右,超过deepid。

总结

  1. 新的loss函数(triplet loss)
  2. 特征维度可以很稀疏128维)(Softmax产生的特征表示向量都很大,一般超过1000维)
  3. 实验效果好,在公开的数据集上表现最好(都超过95%)
  4. 需要的预处理比较少,进行分类,直接计算距离就好了,简单而有效(DeepFace和DeepID需要对齐另外也比PCA + SVM 更加简单)。
原创粉丝点击