facenet学习+练习

0. 摘要

摘要都是都是写给我自己看的废话.

在我接触CNN之前,我一直觉得它是一个晦涩难懂的数学应用.所以刚开始都是抱着敬畏的心里去学习.当我花了段时间看了些后,发现与其称之为科学不如称其为数学技术的应用.各种网络的结构譬如rcnn/yolo/ssd等,只要你找对了文章(要找对了,写的人太多了,不免有些滥竽充数)理解起来是很方便的.直白的讲就是要你造一个轮子来实现某个功能,大家自由发挥.看对的文章,你会发现原理很简单.具体应用的时候可能需要结合一些数学公式.

当然我只是感兴趣拿来玩玩,跑跑,仅限于这个层面.

学习一项知识的时候需要有好奇心和自信心.

在我接触过rcnn/ssd/yolo后,我的心态变了,不在觉得他是多么的高深复杂,遥不可及.当我接触facenet的时候,我的惯性思维又先入为主以为它也是个非常难的,毕竟"不同人脸的特征差异"要远比"不同物体的特征差异"小.但是当我看过facenet的论文后,我又释然了.

谨以此文记录一下facenet的原理(以一个普通学习者的角度,我专业不是搞这个的,就是一时兴起).

1. 简介

facenet的原理很简单,比rcnn/yolo/ssd等都要简单.一言以蔽之:

"提取输入人脸图像的特征(所有的CNN网络都会做这个),通过L2 normalization映射到高维球面(特征维数多可不就是高维空间嘛,做了L2归一化(L2范数为1)后可不就是球面嘛,这些都不用关心啦,我又不是搞研究的),每张人脸图像都对应一个高维球面的特征向量(我们称它为特征向量).判断两张人脸是否是同一个人,可以根据两个特征向量之间的欧式距离(欧式距离这个上过大学的都知道吧,或者上过中学的计算三维空间中两点的距离,坐标相减,然后平方,求和,再开根号)进行判断.欧式距离小于给定的阀值(阀值如何确定:可以在评估模型的时候获取,这个原文里面有讲,我们下面还会再说)则断定为是这两张人脸图片是同一个人的,如果不同那么就不是同一个人的"

好了现在可以去看一下原文了,英语不好的话先去看一下翻译,翻译里有讲的不明白的再去看原文,还不明白的可能就是我下面讲的这几点,再不明白我也就不明白了.

论文翻译文:FaceNet

论文原文:FaceNet: A Unified Embedding for Face Recognition and Clustering

源码: davidsandberg / facenet

 

2. 一些可能花个几分钟才能搞明白的点

看了一遍文章感觉还是有几个点需要再推敲下,就把他们记录在这吧.

(1) 首先,我们先来了解下数据集:

以LFW(Labled Faces in the Wild)人脸数据集为例,它包含了13000多张人脸图片,每张图片上都标注了名字,不同人的图片数量不一样,有1680人有不止一张人脸图片(多的像George_HW_Bush有500张,大部分人只有一张).我们可以通过以下链接来下载改数据集,在左边栏选download(这里有好几个数据集,我就用了第一个,其他的带align的应该是做了人脸对齐,这样检测的时候就不用MTCNN网络了吧,猜测,还没试过,待验证)

Labeled Faces in the Wild Home

 

(2) Loss函数:

我们的目标是使"同一人的一对人脸图片的特征向量欧式距离"尽量小,"不同人的一对人脸图片的特征向量欧式距离"尽可能大.从而诞生了论文中的triplet loss

三元组分别是输入的人脸anchor,正例人脸positive(与anchor是同一人),负例人脸negative.每个minibatch中负例是远远多余正例的,因此需要选出hard positive正例和hard negative负例.实际上作者使用了一个minibatch中的所有正例,挑选了同正例数量一致的hard negative负例(这样提高网络的识别能力,特别是针对那些非常像但又不是同一人的人脸).

(3) 模型评估:

这部分建议看一下英文原文

介绍下val和far:

这里先介绍下val和far两个概念,validation rate(准确率,也即true positive(或者true accpet),是一个人切判断正确的比率),fail accept rate(也即我们的false positive(或者false accpet),就是错误判断为正例的比率,本来是负例给人家判断成正例了,本来不是一个人的被判断成一个人)

这个看公式和解释都能明白,但是不是一眼就看明白的,我再解释下.

val = (TA的数量) / (同一人脸的图片对的数量)  far = (FA的数量) / (不同人脸图片对的数量)

介绍下欧式距离的threshold:

threshold是一个常量,两张人脸的欧式距离大于threshold则断定是不同的人,小于此值则断定是同一人.threshold是我们识别人脸的最重要的判据

文中规定了far为一个极小值(看源码lfw.py的evaluate函数中调用facenet.calculate_val时指定的是1e-3,源码里把它叫做far_target),目的是降低误判率,根据这个值我们就能得到欧式距离的threshold.两张人脸的欧式距离大于此值则是不同的人,小于此值则是同一人.

那么我们的threshold是如何得到的呢:

模型在评估的时候将threshold按照0.01的间距从0取到4,对每个threshold计算一下val,far评估标准数据(根据val,far可以画出roc曲线图,不明白roc是啥去看机器学习基础(1)- ROC曲线理解).总有一个far刚好接近我们设定的far_target,对应的就是我们想要的那个threshold.

为了保证验证的准确性,这里进行了10折交叉验证(就是把样本集均分成10份,9份做训练集,1份做验证集;这样可以训练和验证10次),我们可以得到10组数据.

threshold也可以得到10组数据,这里我取了平均,当然也可以选其他值,譬如想要保证正确性,那就选一个最小的threshold;或者你也可以选择众数...

哦对了,这个threshold源码里默认没有打印出来,需要自己在facenet.py的calculate_val函数中添加打印.

3. 如何进行人脸识别

有了threshold就好办了,我们可以这样设计下.考虑一个场景,譬如你家的智能门禁,需要先把你家三口人ABC的人脸信息录入数据库,包括label(名字)和特征向量;然后有人来的时候计算一下他的人脸特征向量和数据库中的三人的特征向量欧氏距离xyz,找出最小的那个欧式距离,譬如是y,如果y小于threshold,那么这个人就是B;如果y大于threshold那么就是陌生人喽.

开搞,这里仿照compare.py写了个python脚本.

中间有些问题,我用的python3.5,按照requirement.txt安装的包,结果提示我scipy.misc.imread和scipy.misc.imresize不能用,所以我用imageio模块来实现了图像的read和resize.

附我的github链接https://github.com/steveliu121/facenet

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值