用Python實現類Face ID的人臉識別?一文告訴你該怎麼做

文章選自Medium,作者:Norman Di Palo,機器之心編譯

本文介紹了如何使用 Python 在 Keras 框架上實現 FaceID,對 iPhone X 這一新解鎖機制進行了反向工程和概念驗證。想知道 FaceID 背後人臉識別模塊的原理,想自己動手實現帶人臉深度特徵的網路,不妨閱讀此文。

GitHub 地址:github.com/normandipalo

人們對 iPhone X 討論最多的一個功能就是最新的解鎖方式,TouchID 的接替者:FaceID。

隨著蘋果手機邊框面積的減少,蘋果公司必須開發一種更便捷、快速的新型解鎖方式。儘管一些競爭者繼續使用指紋感測器,但是蘋果決定創新,革新手機解鎖方式:即只需要看一眼它。藉助於改進(雖然微小)的前置深度相機,iPhone X 為用戶面部創建了一個 3D 映射圖。此外,用戶人臉照片會通過紅外攝像機捕捉,該攝像機對環境的光線、顏色變化具備更強的魯棒性。使用深度學習,智能手機可以非常細緻地了解用戶面部,從而能在用戶每次拿起手機時快速識別用戶。令人驚訝的是,蘋果稱此方法比 TouchID 更安全,誤差率低至 1:1,000,000。

我對蘋果實現 FaceID 的技術非常感興趣,尤其是它在移動設備端完美運行的原理。FaceID 只需要對用戶面部進行稍微的初始訓練,即可在用戶每次拿起手機時流暢運行。我使用深度學習研究了該流程以及如何優化每一步。本文將展示如何使用 Keras 實現一個類似 FaceID 的演算法。我將對採用的多個架構決策作出解釋,並展示一些最終實驗(實驗使用 Kinect 完成,Kinect 是一個流行的 RGB + 深度相機),實驗輸出與 iPhone X 前置攝像頭類似,不過實驗使用的設備比 iPhone X 大一些。下面我們開始對蘋果這一變革性功能進行反向工程吧。

了解 FaceID

「主導 FaceID 的神經網路不只執行分類任務。」

FaceID 設置流程

第一步:仔細分析 FaceID 在 iPhone X 上的運行原理。蘋果的 FaceID 白皮書(images.apple.com/busine)可以幫助我們理解 FaceID 的基本機制。使用 TouchID 時,用戶必須先通過多次按壓指紋感測器來註冊自己的指紋。在大約 15–20 次按壓之後,手機完成指紋註冊,TouchID 可以使用。類似地,使用 FaceID 時,用戶必須先註冊自己的臉。註冊過程很簡單:用戶只需正常看著手機,緩慢轉動頭部一圈,這樣可以註冊面部的不同姿勢。這樣註冊過程就結束了,用戶可以使用 FaceID 解鎖手機。快速的註冊過程向我們提示了很多底層學習演算法。例如主導 FaceID 的神經網路不只執行分類任務,我會在下文中解釋原因。

蘋果介紹 iPhone X 和 FaceID 的 Keynote

執行分類任務對神經網路而言意味著學習預測它看到的人臉是否屬於用戶。因此,它應該使用一些訓練數據來預測「正類」「負類」。但是與大量深度學習應用案例不同,該方法不適用於人臉識別。如果將該方法應用於人臉識別,那麼首先神經網路應該使用新獲取的用戶面部數據從頭開始重新訓練,這要求大量時間、能耗,以及獲取不同人臉的訓練數據作為負樣本(而這是不切實際的),遷移學習和對訓練好的模型進行精細調整也都需要這些。此外,該方法無法利用這一優勢:即蘋果公司可以「離線」訓練更複雜的網路,即在實驗室訓練好,然後部署到手機上,即裝即用。我認為 FaceID 主要使用是一種類似孿生神經網路的架構,蘋果公司「離線」訓練該網路,然後將人臉映射至低維潛在空間,以最大化不同人面部之間的差距,該網路使用對比損失(contrastive loss)。正如蘋果在 Keynote 中展示的那樣,這樣你就獲得了一個可執行一次學習的架構。

FaceID 似乎是 TouchID 之後的新標準。蘋果會將這一功能應用到所有新設備中嗎?

使用神經網路將面部數值化

孿生神經網路基本上由兩個一樣的神經網路構成,二者共享所有權重。該架構可以學習計算特定數據類型之間的距離,如圖像。即你將成對數據輸入孿生神經網路中(或者在同一個網路中在兩個不同的步中輸入數據),該網路將數據映射至低維特徵空間(類似 n 維數組),然後訓練該網路使不同類別的數據點距離儘可能地遠,同一類別的數據點儘可能地近。在長時間運行中,該網路將學習提取數據中最有意義的特徵,並將其壓縮成數組,創建一個有意義的映射。為了對該過程有一個直觀的理解,你可以想像一下使用小向量描述犬種使類似的犬具備更接近的向量。你可能使用一個數字來編碼皮毛顏色,一個數字表示大小,另一個數字表示毛皮長度等等。很聰明,對吧?孿生神經網路可以學會這麼做,類似自編碼器。

圖源:論文《Dimensionality Reduction by Learning an Invariant Mapping》(Hadsell、Chopra、LeCun)。注意該架構如何學習手寫數字圖像之間的相似性,如何自動將其進行二維分組。類似的技術可應用於人臉

使用該技術,我們可以使用大量人臉數據訓練類似架構,來識別相似度最高的人臉。有足夠的預算和算力(像蘋果那樣),你也可以使用更難的樣本訓練對對抗攻擊(掩碼)等具備魯棒性的網路。那麼使用該方法的最終優勢在哪裡呢?你將擁有一個即插即用的模型,無需訓練即可識別不同的用戶,只需在初始設置時拍一些照片來計算用戶面部在潛在人臉映射空間中的位置。(想像一下,就像寫下一隻新的狗的犬種向量,然後將它存儲在某個地方。)此外,FaceID 能夠適應用戶的改變:不管是突然的改變(如眼鏡、帽子、化妝)還是緩慢的變化(鬍鬚)。這是通過在映射空間中添加參考人臉向量(基於新外表計算得出)來完成

FaceID 可以在用戶面部發生改變時隨之進行調整

最後,我們來看一下如何在 Keras 中用 Python 實現該網路。

在 Keras 中實現 FaceID

所有機器學習項目首先需要的都是數據。創建自己的數據集需要時間和多人寫作,難度較大。因此,我在網上找了一個看起來比較合適的 RGB-D 人臉數據集(vap.aau.dk/rgb-d-face-d),它由一系列人朝著不同方向、帶有不同面部表情的 RGB-D 圖像構成,非常適合 iPhone X 的應用場景。

  • 最終實現的 GitHub 版本庫地址:github.com/normandipalo
  • 使用 Colab Notebook 的實驗:colab.research.google.com

我基於 SqueezeNet 架構創建了一個卷積神經網路,將成對的面部 RGB-D 圖像(即 4 通道圖像)輸入網路,輸出兩個嵌入之間的距離。使用對比損失訓練該網路,以最小化同一個人不同圖像之間的距離,最大化不同人圖像之間的距離。

對比損失

經過一段時間的訓練,該網路能夠將人臉映射至 128 維數組,這樣同一個人的圖像被聚類為一組,而不同人的圖像距離較遠。這意味著要解鎖你的設備,該網路只需計算解鎖時輸入的圖像與註冊階段存儲圖像之間的距離。如果距離在特定閾值以下(閾值越小,安全性越高),則設備解鎖成功。

我使用 t-SNE 演算法對 128 維嵌入空間進行二維可視化。每個顏色對應不同的人:如下圖所示,該網路學會把同一顏色的圖像分到很接近的區域(使用 t-SNE 時,不同簇之間的距離是無意義的)。使用 PCA 降維演算法時,可視化圖也很有意思。

使用 t-SNE 在嵌入空間中創建的人臉集群。每個顏色代表不同的人臉(不過顏色有重複使用)

使用 PCA 在嵌入空間創建的人臉集群。每個顏色代表不同的人臉(不過顏色有重複使用)

實驗

現在我們可以看看該模型的運行效果,使其模擬通常的 FaceID 過程:首先,進行用戶面部註冊。然後是解鎖階段,從用戶解鎖(應該會成功)到其他人解鎖(不會成功)。如前所述,重點在於該網路計算解鎖手機的人臉與註冊人臉之間的距離,及其是否低於特定閾值。

首先開始註冊:我從數據集中抽取了同一個人的一組照片來模擬註冊階段。設備正在計算每個姿勢的嵌入,並存儲在本地。

新用戶註冊階段,受 FaceID 註冊過程啟發

深度相機看到的註冊階段

現在我們來看如果用戶嘗試解鎖設備會發生什麼。同一用戶的不同姿勢和面部表情都達到了極低的距離,平均距離在 0.30 左右。

同一用戶在嵌入空間中的人臉距離

而不同人的 RGB-D 圖像的距離平均值為 1.1。

不同用戶在嵌入空間中的人臉距離

因此,將閾值設置為 0.4,可以防止陌生人解鎖你的設備。

結論

本文介紹了如何基於人臉嵌入和孿生卷積網路實現 FaceID 解鎖機制的概念驗證。希望對大家有所幫助。

原文地址:towardsdatascience.com/


推薦閱讀:

python爬蟲實習?
基於python的scrapy爬蟲,關於增量爬取是怎麼處理的?
用Python搭建一個如下的個人網站學習路線應該是怎麼樣的?
學慣用python來自動化測試(一)
知乎上這麼多推崇學 Python 入IT 行的,如果他們學完 Python這一套找不到工作怎麼辦?

TAG:人臉識別 | FaceID | Python |