跑通FaceNet人脸识别

原创:杨其泓

一、前言

FaceNet是一个十分经典的人脸识别模型,并且具有较好的性能,但要实现使用自己的数据进行人脸识别,还需要对模型进行重新训练。本文将介绍跑通一个简单FaceNet的全部流程,以及踩坑记录。

二、方案技术路线

1. 人脸检测:使用 Dlib 中预先训练的模型检测面部;

2. 人脸校准:使用 Dlib 的实时姿势估计与 OpenCV 的仿射变换来尝试使眼睛和下唇在每个图像上出现在相同位置;

3. 卷积网络:使用深度神经网络把人脸图片映射为 128 维单位超球面上的一个点;

4. 分类:使用三元损失函数对每张图片对应的超球面的点(128维向量)比较相似度以此进行分类。

图片来源:https://cmusatyalab.github.io/openface/


三、参考

3.1 论文

FaceNet: A Unified Embedding for Face Recognition and Clustering.

论文链接:https://arxiv.org/abs/1503.03832

3.2 代码

Github代码链接:https://github.com/foamliu/FaceNet

3.3 数据

训练集

CelebFaces Attributes Dataset (CelebA) 是一个大型的人脸数据集,有10,177个身份和202,599张人脸图像。

 数据链接:

http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html

Celeba数据集是香港中文大学的公开数据集,所以支持百度网盘下载!选择Baidu Drive即可将数据集转存至自己的网盘,Celeba数据集大约有22个G(解压后24左右),所以最好要弄个百度网盘SVIP账号再下。

TODO:数据集详细介绍

测试集

LFW (Labled Faces in the Wild)人脸数据集:是目前人脸识别的常用测试集,共有13233张图像,每张图像均给出对应的人名,共有5749人,尺寸为250X250。

数据官网链接:

http://vis-www.cs.umass.edu/lfw/

(官网链接有详细的数据说明及介绍,看不懂数据是啥的可以来看这个)

数据直接下载链接:

http://vis-www.cs.umass.edu/lfw/lfw-funneled.tgz

(直接下载链接是下下来就能用来跑的)

Linux中直接下载:

$ wget http://vis-www.cs.umass.edu/lfw/lfw-funneled.tgz

$ tar -xvf lfw-funneled.tgz

$ wget http://vis-www.cs.umass.edu/lfw/pairs.txt

$ wget http://vis-www.cs.umass.edu/lfw/people.txt

其实执行前两行就行,后两个文件在Github的文件夹中有了已经。

如果是在自己电脑本地下载验证数据集,可以看到它里面分了好几个文件,里面不光有图片,还有好几个label的txt,但是label文件其实在Github上的data里有了,所以其实用到的就是那个图片。

TODO:数据集详细介绍

3.4 模型权重

Dlib人脸校准模型

shape_predictor_5_face_landmarks.dat.bz2链接:

http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2

本项目的人脸检测部分直接使用DLIB来实现,并且通过DLIB的关键点来进行人脸平面对齐,所以需要下载相关模型权重。

FaceNet 人脸识别模型

model.10-0.0156.hdf5链接:

https://github.com/foamliu/FaceNet/releases/download/v1.0/model.10-0.0156.hdf5

这个是作者训练好的一个模型,可以直接用来预测。(模型保存的名称是epoch数-损失,但在后续训练过程中,大家可能会发现在第10个epoch不可能训练到这样的精度,我认为可能是训练中断后重新训练,但是没有调整初始计数造成的)

3.5 配置环境

硬件环境:

系统:Linux

4个RTX2080ti GPU,显存12G(训练使用了俩,只用一个的话会OOM内存溢出)

主要依赖项:

TensorFlow-gpu==1.13.1

Keras==2.2.4

OpenCV-python==4.2.0.32

Dlib==1.19.0

四、代码运行

4.1 前期准备

数据:

将两套数据文件解压后放在data文件夹中,data文件夹如下图所示:

模型:

将两个模型权重放在models文件夹中(因为训练的时候存了很多权重这里就不截图了)。

4.2 数据预处理

进入FaceNet-master/目录,运行:

$ python pre-process.py

这里主要是通过DLIB对Celeba数据进行预处理,包括人脸检测、人脸5特征点检测、人脸对齐等。总共 202,599张人脸图像中,5600张无法被 dlib 标定。因此 202599 - 5600 = 196999 张被用于训练。大约耗时15-20分钟左右。

4.3 模型训练

运行:

$ python train.py

4.4 模型评估

运行:

$ python lfw_eval.py

使用LFW数据集对模型进行验证,输出结果为ROC曲线面积。

五、踩坑记录

5.1 DLIB安装

DLIB可能需要如下前置配置(根据系统差异配置可能有所不同):

X11(xquartz)

Cmake

前置配置安装完成后,一般可用pip install dlib直接安装。

5.2 Keras预训练权重下载

此套代码的核心模型是keras自带的inception_resnet_v2,:

这个代码在执行的时候,会自动去下载这个模型的预训练权重(keras自己公布的几个重点模型的预训练权重),文件大小大约在209M,但是下载会很卡,解决方法是重新下,不停的重新下,或者尝试科学上网,这个在我的mac上极其有效,如果还是下不下来,可以在百度找这个模型权重的文件手动下载,百度上说下载完成后保存在.models文件中(mac或linux中.开头的文件应该是隐藏文件),但是我找了好久都没有找到这个文件夹,后来才发现,他是在我的根目录里!而不是site-packges下面的keras里:

找到位置,下对文件,放进来就ok了。

5.3 get_random_triplets函数

data_generator.py文件中使用了函数get_random_triplets():

但是,在utils.py文件中定义的这个函数并没有输入项,

所以那个括号里的‘train’是多余的,需要删除,要不会报错。

5.4 np.array大计算量报错

我的环境里,最开始keras的版本是2.1.5(好像是,反正是2.1开头的),在进行训练时,报:

StopIteration: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'B') according to the casting rule ''same_kind''

这个错误的本质是:在对numpy的dnarray数组使用类似+=的运算符时候(比如y+=c),如果数组复杂到一定程度,这样的自加运算就会报如上的错。解决方案就是不使用+=等写法(不使用数学符号的写法),转而使用add等api,但是程序报这个错的具体位置是在keras里,有一行使用了/=,所以这里使用上述修改方法是不稳妥的,毕竟是要改keras源码,一是有大量的此类计算符的话难以处理,二是还要做备份,所以这条路暂时走不通,继而我想到,提高keras版本是否能解决此问题,高本版的keras是否对此进行了优化,结果是,是的,提高版本即可(但要注意keras和TensorFlow的版本匹配关系,不能过高)。

5.5 OOM显存溢出

这个Facenet使用的是keras内部自带的inception_resnet_v2网络,共计5000多万个可训练参数,输入图片大小为139*139,默认batchsize为128,因此训练这个模型的显存占用是极大的,我的显卡是12G显存,实际能用的是10个g多一点,只使用一块卡的话会直接报显存溢出OOM,我还尝试过两块卡,batchsize为256,依然溢出,所以应该视情况对batchsize进行控制,或者考虑换用其他模型(这个其实我一上来就想换过,毕竟是直接走keras调用的,但是由于调用的地方很多以及需要模型指定层的输出,所以还不能随便替换,需要提前去了解一下其他模型的及具体结构)。

5.6 数据缺失

我一开始下载了Celeba数据,就开始尝试进行模型训练了,但是后来报了‘nonetype object has no attribute’,经过判断我发现是image为空,也就是没有读到数据,后来发现:这套github的代码使用了Celeba数据及LFW数据,前者用来训练,候着用来验证及出精确度,但是并不是按常用的方法将训练集拆分成一定比例进行训练、验证,用单独的数据及测试,而是直接调用训练集进行训练,在每个epoch的出验证集损失的时候直接调用LFW数据(可以通过看fit_generator的参数来证明这点),并在进行模型评估的时候只使用LFW数据,这也就意味着,必须同时下好这两套数据才能顺利进行训练。

5.7 Accuracy计算

模型评估代码的最后,会自动打印模型accuracy,我第一反应是常规上理解的accuracy,也就是PP=TP/(TP+FP),然而,这里虽然print写的是accuracy,但实际上计算的是ROC曲线下的面积,也就是AUC。计算关键部位代码如下:

这几个评价指标的区别到底是什么呢?

图片来源:https://www.deeplearn.me/1522.html


如图所示,正确率的计算公式就是TP/(TP+FP);

而ROC曲线是由tpr=TP/(TP+FN)和fpr=FN/(TP+N)计算而来的。

ROC曲线的特性在于:当测试集中的正负样本的分布变化的时候,ROC 曲线能够保持不变。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容