本文介紹瞭如何使用 Python 在 Keras 框架上實現 FaceID,對 iPhone X 這一新解鎖機制進行了反向工程和概念驗證。想知道 FaceID 背後人臉識別模組的原理,想自己動手實現帶人臉深度特徵的網路,不妨閱讀此文。
GitHub 地址:https://github.com/normandipalo/faceID_beta
人們對 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 白皮書(https://images.apple.com/business/docs/FaceID_Security_Guide.pdf)可以幫助我們理解 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 人臉資料集(http://www.vap.aau.dk/rgb-d-face-database/),它由一系列人朝著不同方向、帶有不同面部表情的 RGB-D 影像構成,非常適合 iPhone X 的應用場景。
最終實現的 GitHub 版本庫地址:https://github.com/normandipalo/faceID_beta
使用 Colab Notebook 的實驗:https://colab.research.google.com/drive/1OynWNoWF6POTcRGFG4V7KW_EGIkUmLYI
我基於 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 解鎖機制的概念驗證。希望對大家有所幫助。