如何使用InsightFace做人臉識別訓練?

語言: CN / TW / HK

## 什麼是 InsightFace

InsightFace 是一個與人臉檢測、人臉識別有關的工具箱。已經被封裝好 Python Package,達到了開箱即用的效果。其上層介面可以直接做人臉檢測、性別判斷等。其底層實現其實是訓練好的各類模型。

OneFlow 提供的模型是 InsightFace 專案的後端之一。

關於 InsightFace 的推理效果展示,可以參考 OneFlow 雲平臺上的專案 人臉識別許可權系統演示

本專案主要介紹與超大規模人臉識別訓練有關的原理和技術實踐。

如何使用該專案

首先,需要註冊OneFlow雲平臺的賬號,進入本專案並 “Fork” 。然後點選“執行”,連線容器,執行以下命令。

cd /workspace && bash ./train_graph_distributed.sh

會有類似如下輸出,分別包含了:

  • 訓練的基本配置

Training: 2021-12-14 14:49:44,690-rank_id: 0 Training: 2021-12-14 14:49:44,720-: loss                     cosface Training: 2021-12-14 14:49:44,720-: network                 r50 Training: 2021-12-14 14:49:44,720-: resume                   False Training: 2021-12-14 14:49:44,720-: output                   model Training: 2021-12-14 14:49:44,720-: dataset                 ms1m-retinaface-t1 Training: 2021-12-14 14:49:44,720-: embedding_size           512 Training: 2021-12-14 14:49:44,721-: fp16                     True Training: 2021-12-14 14:49:44,721-: model_parallel           True Training: 2021-12-14 14:49:44,721-: sample_rate             0.1 Training: 2021-12-14 14:49:44,721-: partial_fc               0 Training: 2021-12-14 14:49:44,721-: graph                   True Training: 2021-12-14 14:49:44,721-: synthetic               False Training: 2021-12-14 14:49:44,721-: scale_grad               False Training: 2021-12-14 14:49:44,721-: momentum                 0.9 Training: 2021-12-14 14:49:44,721-: weight_decay             0.0005 Training: 2021-12-14 14:49:44,722-: batch_size               128 Training: 2021-12-14 14:49:44,722-: lr                       0.1 Training: 2021-12-14 14:49:44,722-: val_image_num           {'lfw': 12000, 'cfp_fp': 14000, 'agedb_30': 12000} Training: 2021-12-14 14:49:44,722-: ofrecord_path           /dataset/18fad635/v1/ofrecord Training: 2021-12-14 14:49:44,722-: num_classes             93432 Training: 2021-12-14 14:49:44,722-: num_image               5179510 Training: 2021-12-14 14:49:44,722-: num_epoch               25 Training: 2021-12-14 14:49:44,722-: warmup_epoch             -1 Training: 2021-12-14 14:49:44,722-: decay_epoch             [10, 16, 22] Training: 2021-12-14 14:49:44,723-: val_targets             ['lfw', 'cfp_fp', 'agedb_30'] Training: 2021-12-14 14:49:44,723-: ofrecord_part_num       32

  • 載入驗證集資料的日誌

Training: 2021-12-14 14:49:50,124-loading bin:0 Training: 2021-12-14 14:49:51,372-loading bin:1000 Training: 2021-12-14 14:49:52,649-loading bin:2000 Training: 2021-12-14 14:50:17,039-loading bin:9000 Training: 2021-12-14 14:50:18,300-loading bin:10000 Training: 2021-12-14 14:50:19,576-loading bin:11000 Training: 2021-12-14 14:50:20,839-loading bin:12000 Training: 2021-12-14 14:50:22,099-loading bin:13000 Training: 2021-12-14 14:50:23,353-oneflow.Size([14000, 3, 112, 112]) Training: 2021-12-14 14:50:23,709-loading bin:0 Training: 2021-12-14 14:50:24,991-loading bin:1000 Training: 2021-12-14 14:50:26,292-loading bin:2000 Training: 2021-12-14 14:50:27,590-loading bin:3000 Training: 2021-12-14 14:50:28,886-loading bin:4000 Training: 2021-12-14 14:50:30,174-loading bin:5000 Training: 2021-12-14 14:50:31,463-loading bin:6000 Training: 2021-12-14 14:50:32,744-loading bin:7000 Training: 2021-12-14 14:50:34,029-loading bin:8000 Training: 2021-12-14 14:50:35,315-loading bin:9000 Training: 2021-12-14 14:50:36,593-loading bin:10000 Training: 2021-12-14 14:50:37,867-loading bin:11000 Training: 2021-12-14 14:50:39,144-oneflow.Size([12000, 3, 112, 112])

  • 訓練時的基本資訊(速度、loss 變化、預估剩餘時間等)

Training: 2021-12-14 14:51:02,452-Speed 883.82 samples/sec   Loss 52.6974   LearningRate 0.1000   Epoch: 0   Global Step: 100   Required: 202 hours Training: 2021-12-14 14:51:09,722-Speed 880.33 samples/sec   Loss 53.4146   LearningRate 0.1000   Epoch: 0   Global Step: 150   Required: 149 hours Training: 2021-12-14 14:51:16,968-Speed 883.24 samples/sec   Loss 51.8446   LearningRate 0.1000   Epoch: 0   Global Step: 200   Required: 122 hours Training: 2021-12-14 14:51:24,237-Speed 880.57 samples/sec   Loss 50.9537   LearningRate 0.1000   Epoch: 0   Global Step: 250   Required: 106 hours Training: 2021-12-14 14:51:31,526-Speed 877.99 samples/sec   Loss 50.5335   LearningRate 0.1000   Epoch: 0   Global Step: 300   Required: 95 hours Training: 2021-12-14 14:51:38,831-Speed 876.17 samples/sec   Loss 49.6624   LearningRate 0.1000   Epoch: 0   Global Step: 350   Required: 87 hours Training: 2021-12-14 14:51:46,151-Speed 874.42 samples/sec   Loss 48.9462   LearningRate 0.1000   Epoch: 0   Global Step: 400   Required: 82 hours Training: 2021-12-14 14:51:53,476-Speed 873.76 samples/sec   Loss 48.3082   LearningRate 0.1000   Epoch: 0   Global Step: 450   Required: 77 hours Training: 2021-12-14 14:52:00,810-Speed 872.72 samples/sec   Loss 48.0000   LearningRate 0.1000   Epoch: 0   Global Step: 500   Required: 73 hours

其中剩餘時間一項,開始階段會有短暫的波動,屬於正常現象。會隨著靜態圖構圖完成,逐漸穩定、準確。 訓練完成後,訓練日誌和模型儲存在 /workspace/model/下面。

人臉識別訓練的技術演變

在深度學習領域,被大家最為津津樂道的一個故事,是Hiton 在神經網路遇冷期,堅守數十年,終於在2012年,帶領學生攜 AlexNet,參加了 Imagnet 的影象識別比賽,一舉奪冠,並且準確率比同行一下高出好幾個百分點,從此開啟了深度學習的時代。

深度學習主要特點,就是利用深度神經網路,作為特徵提取器,進行端到端的特徵提取,取代了傳統機器學習中需要嚴重依賴人工設計特徵提取規則的方法。

基於深度學習的人臉識別,也從2014年 DeepID(CVPR 2014) 將卷積神經網路引入人臉識別的演算法開始,到2019年的 InsightFace,基本趨於成熟。

深度學習的過程,直觀地理解是通過損失函式作為優化目標,然後通過迭代式的優化方法,比如我們熟知的梯度下降法,指導模型從大資料中發現規律,並將學習到的經驗沉澱到神經網路的引數上面。

人臉識別模型多使用卷積神經網路,尤其是2015年出現的 ResNet,在影象領域的有著非常優秀表現,因此,近年來,人臉識別在模型上的創新不多,基本上都是基於卷積神經網路。人臉識別技術的創新,很大程度上,是損失函式的創新。

從普通常見的 Softmax Loss 到 InsightFace 所使用的 ArcFace Loss,演變過程如下圖所示:

image.png

在本專案中,主要實現了cosface 和arcface兩種最常用的 loss,程式碼如下,oneflow原生介面支援用房方便的設定m1、m2和m3:

```

loss

if cfg.loss == "cosface":   self.margin_softmax = flow.nn.CombinedMarginLoss(1, 0., 0.4).to("cuda") else:   self.margin_softmax = flow.nn.CombinedMarginLoss(1, 0.5, 0.).to("cuda") ```

它對應的數學公式是:

image.png

OneFlow 如何簡單優雅地解決超大規模人臉識別訓練難題

工業界的實際應用中,遇到的人臉ID規模,可能是上千萬、上億級別的,這時候,單機單卡無法完成訓練。 通常框架支援的成熟並行方案只有資料並行,簡單的資料並行,也是無法高效支援超大規模人臉識別訓練的。

關於分散式訓練的常見策略,和相關基礎知識,可以參考 常見的分散式並行策略

超大規模人臉識別的訓練模型的特點是:

  1. 最後的全連線層計算量巨大,佔用較高的視訊記憶體
  2. 作為特徵提取器的前半部分的卷積神經網路並不算很大

這樣的特點使得它既不適合用純資料並行,也不適合用純模型並行,而是適合使用混合並行:作為特徵提取器的卷積網路使用資料並行,全連線層用模型並行,這樣效率是最高的。oneflow還原生介面支援Partial FC,可以進一步降低全連線層的計算量,極大的降低視訊記憶體的佔用。oneflow優化實現的並行Softmax可以進一步加快訓練速度,原理實現介紹:如何實現一個高效的Softmax CUDA kernel

本專案中的相關實現:

```

function.py line :118

self.backbone = backbone.to_consistent(placement=placement, sbp=flow.sbp.broadcast) ```

以上程式碼讓作為特徵提取器的卷積網路,做資料並行訓練。

```

function.py line :110~117

if cfg.model_parallel:   input_size = cfg.embedding_size   output_size = int(cfg.num_classes/world_size)   self.fc = FC7(input_size, output_size, cfg, partial_fc=cfg.partial_fc).to_consistent(   placement=placement, sbp=flow.sbp.split(0)) else:   self.fc = FC7(cfg.embedding_size, cfg.num_classes, cfg).to_consistent(   placement=placement, sbp=flow.sbp.broadcast) ```

以上程式碼,讓全連線層做模型並行訓練。

其它的通訊、排程、同步等統統交給 OneFlow 高效完成。

更多詳細內容,請看我們的官方教程:InsightFace 從青銅到王者