用 Google 的 FaceNet 做人脸识别---极客帮课程笔记
前几天在极客帮学了一个课程, 应班主任的要求, 做一个笔记;
课程的主要内容是Google开源的机器学习平台 TensorFlow 和人脸识别模型 FaceNet, 这里重点介绍一下人脸识别;
1. 环境搭建:
课程的代码运行在 TensorFlow 1.12 版本上的, 下面是 TensorFlow 1.12 版本的环境安装步骤(Win10);
安装 python3.6.8;
安装 cmake;
安装 visual studio c++ 社区版;
安装 pipx:
python -m pip install --user pipx python -m pipx ensurepath pipx completions
用 virtualenv 建立一个隔离的 python 环境, 我们把这个隔离的环境放到 tf 目录下:
pipx install virtualenv python -m venv tf virtualenv --system-site-packages -p python3.6 ./tf
进入我们的隔离环境 tf;
.\tf\Scripts\activate
安装 TensorFlow:
pip3 install tensorflow==1.12
安装 python 代码编辑器 jupyter:
pip3 install jupyter
安装绘图库, keras, opencv 等等:
pip3 install tensorflow==1.12 pip3 install jupyter pip3 install matplotlib pip3 install pandas pip3 install seaborn pip3 install numpy pip3 install keras==2.1.3 pip3 install h5py==2.10.0 pip3 install opencv-python pip3 install face_recognition pip install sklearn pip install dlib==18.17.100
给 jupyter 安装kernel:
jupyter kernelspec list
python -m ipykernel install --user --name=tf
运行 jupyter notebook, 就可以打开python 编辑环境了;
2. FaceNet人脸识别:
课程里使用 OpenFace 做人脸特征向量提取, OpenFace 是基于2015年 Google 的关于 FaceNet 的论文实现的, 基于深度神经网络;
使用预先训练好的模型, 大概是三百多万张人脸训练出来的模型;
大体逻辑是这样的:
OpenCV读取图片 -> AlignDlib 提取人像 -> 截取人脸 -> 用 OpenFace 提取人脸特征向量 -> 用近邻分类(KNN)将测试的人脸分成不同的人;
我们用杨幂和范冰冰的图片示例一下:
看看代码的运行效果:
用OpenCV 加载一张图片:
截取出人脸:
打印出原图, AlignDlib检测的人脸坐标, 和截取后的图像:
用神经网络获取人脸特征向量, 模型是 OpenFace 训练好的模型, 模型比较复杂, 里面封装了卷积, 池化, 等等的操作;
人脸特征向量保存在 embedded 数组, 每个人脸都被嵌入成了超球面空间上的一个点, 翻译成白话就是128维空间上的一个点;
为什么是128维 --- Google 测试了64维, 128维, 256维... 最终得出结论是 128维空间上准确率最好;
128维空间上的两点之间的距离就是欧式距离, 如果有x1坐标到x128坐标, 欧式距离是两点距离x1差值的平方加上x2差值的平方加上x3差值的平方, 一直累加到x128差值的平方, 然后求和, 再求一个开根号;
我们看看128维空间上两张图片的欧式距离;
可以看到, 同一个人的不同照片, 他们在128维空间上的欧式距离很短, 这是因为模型使用 Google 的 Triplet Loss 损失函数训练出来的, 看一下这个损失函数:
大体意思是, 一组数据集, 取一个锚点, 对同一个人, 两张图片在128维空间上的欧式距离最远, 对不同的人, 两张图片在128维空间上欧式距离最近 , 加上阈值, 得到损失值, 将损失值反馈到神经网络, 由神经网络来调整权重;
128维欧式空间距离很短两个点, 小于阈值, 我们认为就是同一个人;
对得到的128维的人脸特征向量, 我们可以用 KNeighborsClassifier 来分类, 度量指标是欧几里得距离, 就是欧式距离;
KNeighborsClassifier (邻近算法) 的大体意思就是近邻分类, 距离比较近的一组点分到一个类别中;
我们找一个测试图片看看效果:
对于128维空间上的点, 我们无法观测, 我们可以借助一些降维工具来辅助, 列如 TSNE;
我们用 TSNE 把杨幂和范冰冰128维空间上的点降维到3维空间看看(杨幂和范冰冰分别有10张图片, 在128维空间上分别有10个点):
三维空间观测起来有点费力气, 我们再降到2维空间试试:
可以看到, 这些点的分布并不是很理想; 原因是和 OpenFace 的训练集有关系, 感兴趣的小伙伴可以自己研究;
后记:
FaceNet 提取出来的人脸特征向量是128维的向量, 除了分类, 还可以做相似搜索之类的东西, 比如利用一些向量数据库做检索, 可以判断哪些人长得像;
完