前幾天在極客幫學了一個課程, 應班主任的要求, 做一個筆記;
課程的主要內容是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維的向量, 除了分類, 還可以做相似搜索之類的東西, 比如利用一些向量數據庫做檢索, 可以判斷哪些人長得像;
完