1. 程式人生 > >[計算機視覺]從零開始構建一個微軟how-old.net服務/面部屬性識別

[計算機視覺]從零開始構建一個微軟how-old.net服務/面部屬性識別

大概兩三年前微軟釋出了一個基於Cognitive Service API的how-old.net網站,使用者可以上傳一張包含人臉的照片,後臺通過呼叫深度學習演算法可以預測照片中的人臉、年齡以及性別,然後將結果繪製到原圖片上返回給使用者。那時候深度學習技術在國內剛流行不久(2016年前後),當時這個網站一度引起IT/非IT界的關注。現在已經過去三四年了,深度學習技術在國內網際網路‘日漸普及’,大家也見怪不怪。本篇文章從零開始,教大家實現一個類似how-old.net的服務,即通過一張包含了人臉的照片,預測年齡、性別以及種族。

熟悉英文的同學可以直接移步github原始碼閱讀README檔案。

 

任務目標

我們的目標很簡單,構建一個神經網路,或者基於已有比較流行的網路結構進行改造,通過素材資料訓練後,我們的網路能夠預測照片中每張人臉的年齡、性別以及種族。最後將結果繪製顯示在原圖片中。我們主要目標是完成神經網路的訓練以及推理和結果顯示,至於完整實現how-old.net需要考慮的那種Web get/post restful API請求暫不需要考慮了,畢竟不是本文重點。

 

工具準備

訓練神經網路或者做深度學習相關的工作,我們最好有一臺帶有GPU的電腦,一般都是Ubuntu系統,但是我這篇文章的程式碼是在自己辦公PC上開發除錯的,有些開源專案並不官方支援Windows10系統,因為這個系統坑比較多,建議大家平時除錯還是優先使用Ubuntu。

  • Windows 10

  • Python 3.5

  • tensorflow-gpu 2.1

  • dib/face_recognition (demo中檢測人臉)

  • OpenCV3.4

  • scipy、numpy、h5py、pillow

  • Cuda 10.0

  • Cudnn 7.5

  • CPU i7-7700K 4.2GHz

  • GPU GTX 1080

  • 16G RAM

我這個硬體配置相對來講算是比較高了,差點的機器也能跑,可能訓練慢點,推理也慢點。

 

實現原理

如果對深度學習有一點了解,那麼解決本次問題的原理其實相當明瞭。這是一個典型的分類問題(分類和迴歸的區別請參見這裡:https://www.cnblogs.com/xiaozhi_5638/p/11792274.html),我們可以定義三個單獨的網路分別去預測年齡、性別以及種族,也可以只定義一個網路(包含三個輸出)同時預測年齡、性別以及種族,前者訓練相對來講簡單、網路更容易擬合,但是網路訓練完之後實際上線推理速度相對要慢,因為需要推理三次(下圖中間),或者並行推理(最上面,需要同時佔用硬體資源),而後者訓練麻煩,收斂效果可能沒有前者好,但是一旦訓練完成後,後面推理速度較快,一次推理出三種結果(下圖最下面)。我們本次採用後面那種方式,即定義一個網路,能夠同時推理出年齡、性別以及種族。

神經網路的訓練有兩種方式,一種從零開始,網路的權重隨機初始化,之後權重調整全靠你自己的資料集;另外一種方式就是在別人已經訓練好的權重基礎上再去調整,以到達解決我們自己任務的目的,這種方式的好處就是網路的權重不再是隨機初始化了,而是初始化為一些比較靠譜的值,我們再在這些靠譜的值基礎上進行調整,這種方式肯定比隨機初始化要好。除非你的資料集相當龐大並且豐富,否則神經網路的訓練一般都是採用使用第二種方式。第二種方式也叫“遷移學習”,類似將別人學習好了的經驗拿過來用,這樣當然要比從零開始學習更容易。遷移學習的關鍵點是要能找到合適的、跟我們任務類似的、別人訓練好的權重,這句話比較拗口,簡單來講就是,你借鑑的經驗必須是有效的,別人10年釣魚的經驗對於你去考駕照來講是無效的,同樣的,你不能借鑑別人10年開車的經驗來學習Python程式設計。那麼什麼經驗是有效的呢?舉幾個例子,你可以借鑑別人10年開車的經驗去學習叉車操控,你也可以借鑑別人學Java程式設計的經驗去學習Python程式設計。對深度學習來講,如果別人已經訓練好了一個網路,該網路可以做1000個人的人臉分類,那麼你可以‘借用’這個網路的權重去做另外100個人的人臉分類(這100不在1000之內),因為這兩個任務有相似性。如果別人已經訓練好了一個網路,該網路可以用來為藝術系學生的水彩畫作業打分,那麼你不可以(或者很難)‘借用’這個網路的權重去為藝術系學生的素描畫作業打分,因為水彩畫和素描畫相關性不是很大。當然,這裡的能不能借用並不是絕對的,只是能借用程度的多少不一。在實際遷移學習訓練過程中,我們可以通過‘凍結’部分網路層的權重,讓其不參與我們自己資料集的訓練,保持初始值不變,那麼這些凍結層的權重就是我們前面說的到‘借用’了,凍結哪些層可以隨機調整,代表我們借用的程度。關於遷移學習更具體的數學描述請參考這篇文章:https://www.cnblogs.com/xiaozhi_5638/p/12202074.html

 

實現過程

解決本次任務時,我們借用牛津大學著名的VGGFace網路結構和其權重,該網路主要用來對2622(VGGFace V1)以及8631(VGGFace V2)個人臉進行分類,網路結構和預訓練的權重在網路上均可以下載。我們的任務目標是對人臉的年齡、性別以及種族進行預測,任務型別和VGGFace差不多,都跟人臉有關,所以遷移學習在這裡完全可以使用。具體做法為:

(1)去掉原VGGFace V2頂部的分類全連線層(MLP層),該層主要對前面提取的人臉特徵進行8631分類;

(2)再在(1)的基礎上接上3個輸出分支,每個分支都是做分類任務,分別負責年齡、性別以及種族的預測;

(3)修改原VGGFace V2的輸入尺寸,由原來的(224, 224, 3)改為(200, 200, 3),主要原因是我們自己的訓練資料集UTKFace的原始尺寸是200*200,當然你也可以保持不變,訓練時將影象縮放;

(4)凍結VGGFace V2網路結構的全部層(不包括我們接上去的3個分支),這個意思是借用VGGFace V2的全部經驗,權重保持不變;

(5)開始使用UTKFace資料集進行訓練;

(6)觀察loss的變化效果,如果發現效果不理想,可以適當回到(4)步,將凍結層數減少,這個意思是借用部分VGGFace V2的經驗;

當然了,網路的訓練遠沒有上面寫的這麼簡單,需要不斷去嘗試,修改各種超引數、甚至調整VGGFace V2本身網路結構(部分權重忽略)。

 

這裡再說一下,為什麼年齡預測是一個分類問題而不是迴歸問題?其實有一篇論文對這個有介紹:https://www.cv-foundation.org/openaccess/content_iccv_2015_workshops/w11/papers/Rothe_DEX_Deep_EXpectation_ICCV_2015_paper.pdf 這個論文用實驗結果告訴我們分類比迴歸的效果要好。下面是使用UTKFace資料集進行訓練的結果,圖中藍色線為val_loss,圖中橙色線條為train_loss,由於訓練過程中使用了資料增強,train_loss比val_loss要高一點,屬於正常現象:

 

原始碼介紹

face.py

定義我們自己的神經網路結構,輸入尺寸,凍結層數等等,可以根據需要自己調整。

 

face_train.py

使用UTKFace資料集訓練我們的神經網路,你可以修改程式碼來適配其他資料集。

 

face_demo.py

單張圖demo

 

face_video_demo.py

視訊檔案demo,或者usb 攝像頭demo

 

face_weights/

訓練過程中,ModelCheckPoint產生的權重檔案,demo可以通過model.load_weights()載入使用。

 

train_data/

存放訓練資料。

 

vggface_weights/

原VGGFace V2預訓練的權重檔案,我們在訓練的時候需要先載入該權重,然後再在基礎上進行微調。注意我使用的是ResNet50的結構,VGGFaceV2內部還支援SeNet50的網路結構。

使用不同的網路結構需要使用不同的預訓練權重。

 

logs/

Tensorboard產生的日誌檔案,用於對訓練進度的監控。

 

多說無益,直接看原始碼更易懂,更多細節請關注公眾號。建國同志和大大鎮樓。

 

參考

websites

  • keras_vggface
  • Oxford VGGFace

datasets

  • VGGFace Dataset used for pre-trained weights (VGGFace V1)
  • VGGFace2 Dataset used for pre-trained weights (VGGFace V2)
  • UTKFace Dataset used for fine-tuning in this repo

papers

  • related paper1 why age estimation is a classification task?
  • related paper2 about VGGFace dataset
  • related paper3 about VGGFace2 dataset
  • related paper4 triplet loss in face recognition

 

 

歷史文章

[計算機視覺]人臉應用:人臉檢測、人臉對比、五官檢測、眨眼檢測、活體檢測、疲勞檢測 

[AI開發]一個例子說明機器學習和深度學習的關係  

[AI開發]零程式碼公式讓你明白神經網路的輸入輸出  

[AI開發]小型資料集解決實際工程問題——交通擁堵、交通事故實時告警   

[AI開發]零程式碼分析視訊結構化類應用結構設計  

[AI開發]零數學公式告訴你什麼是(卷積)神經網路  

[AI開發]視訊結構化類應用的侷限性   

[計算機視覺]基於內容的影象搜尋實現 

[AI開發]目標檢測之素材標註  

關注公眾號,及時關注文章