1. 程式人生 > >[深度學習論文閱讀]Facenet論文閱讀筆記(包括GoogLenet引數計算方式)

[深度學習論文閱讀]Facenet論文閱讀筆記(包括GoogLenet引數計算方式)

1 統述

  • 功能:face verification (is this the same person)
    recognition (who is this person)
    clustering (find common people among these faces)

  • 人臉識別方向論文總結:
    一,識別精度超過0.95(超過人類的識別準確度)
    二,公佈了方法(部分結果為商業公司提交,方法並未公佈,比如Tencent-BestImage)
    三,使用深度學習方,近兩年的結果。
    1,face++(0.9950 );2,DeepFace(0.9735 );3,FR+FCN(0.9645 );4,DeepID(0.9745 );5,FaceNet(0.9963 );6,baidu的方法(0.9977 );7,pose+shape+expression augmentation(0.9807);8,CNN-3DMM estimation(0.9235 ,準確率沒那麼高,但是值得參考)。

    https://zhuanlan.zhihu.com/p/24816781

Facenet一些特點:

  • 與其他的深度學習方法在人臉上的應用不同,FaceNet並沒有用傳統的softmax的方式去進行分類學習,然後抽取其中某一層作為特徵,而是直接進行端對端學習一個從影象到歐式空間的編碼方法(Euclidean embedding),然後基於這個編碼在嵌入空間(embedding space)用(歐氏距離)L2 distance對比做人臉識別、人臉驗證和人臉聚類等。FaceNet演算法有如下要點:

  • 去掉了最後的softmax,而是用三元組計算距離的方式來進行模型的訓練。使用這種方式學到的影象表示非常緊緻,使用128位足矣。(特徵向量的維度選擇問題,維度約小計算越快,但是太小的話很難區分不同圖片;維度越大越容易區分不同圖片,但是太大訓練模型不易收斂,且測試時計算慢,佔用空間大。作者實驗證明 128 維的特徵能夠較好的平衡這個問題)

  • 三元組的選擇非常重要,選的好可以很快的收斂

用歐氏距離判斷人臉是否相似的例子 :
這裡寫圖片描述
如果是一個人的照片,他們的距離就會低於這個閥值,此處應該是1.1左右。這個有點類似於LDA的思想了。類內的距離就小,類間的距離就大,其實本質上並沒有什麼差別。

2 FaceNet總體架構

這裡寫圖片描述
Deep Architecture就是卷積神經網路去掉softmax後的結構,經過L2的歸一化(f(x)2=1所有影象的特徵都會被對映到一個超球面上),然後得到特徵表示,基於這個特徵表示計算三元組損失(本文章最大特點提出triplet loss)。

目標函式(Triplet loss)

這裡寫圖片描述
所謂的三元組就是三個樣例,如(anchor, positive, negative),其中,a和p是同一類,a和n是不同類。那麼學習的過程就是學到一種表示,對於儘可能多的三元組,使得anchor和positive的距離,小於anchor和negative的距離。
上面的思想用數學公式可以表示為
這裡寫圖片描述


經過等價轉換後可以得到Triplet loss函式
這裡寫圖片描述

  • 這裡距離用歐式距離度量,+表示[]內的值大於零的時候,取該值為損失,小於零的時候,損失為零。
  • 由目標函式可以看出:
    xaxn之間的距離小於xaxp之間的距離加α時,[ ]內的值大於零,就會產生損失。
    xaxn之間的距離 >= xaxp之間的距離加α時,損失為零。

triplet loss梯度推導

這裡寫圖片描述
這裡有一個小trick,因為導數的結果在上面的loss中已經計算了一些可以在程式設計時儲存減少計算量

三元組的選取

首先最容易想到的從所有樣本中找出離他最近的反例和離它最遠的正例,然後進行優化。
缺點

  • 容易受不好的資料的主導
  • 導致得到的模型會陷入區域性最優甚至崩潰。

所以,為了解決上述問題

線上生成triplet,在每一個mini-batch中選擇hard pos/neg 樣例(即MBGD方法不使用BGD與SGD方法)。

argmaxf(xai)f(xpi)2
argminf(xai)f(xni)2
1. 為了使mini-batch中生成的triplet合理,生成mini-batch的時候,保證每個mini-batch中每個人平均有40張圖片。然後隨機加一些反例進去。在生成triplet的時候,找出所有的anchor-pos對,然後對每個anchor-pos對找出其hard neg樣本。這裡,並不是嚴格的去找hard的anchor-pos對,找出所有的anchor-pos對訓練的收斂速度也很快。
2. 除了上述策略外,還可能會選擇一些semi-hard的樣例,所謂的semi-hard即不考慮alpha因素,Batch size大約1800個樣例40個正樣例,下面所示為semi-hard條件:
這裡寫圖片描述

3 深度網路架構(即2中Deep Architecture部分)

這個部分是可以更改的,本文主要討論GoogLenet;在FaceNet文章中有兩種網路結構:
1. ZFnet
2. GoogLenet (Inception結構將稀疏矩陣聚類為較為密集的子矩陣來提高計算效能而又不會產生太多的引數)

下面是GoogLenet的inception結構:這裡寫圖片描述

Facenet應用的GoogLenet網路結構

FaceNet中應用的GoogLenet結構與原來的結構有一些不同
下圖是GoogLenet的結構
這裡寫圖片描述
下面是Facenet中GoogLenet結構圖
這裡寫圖片描述
下面講解GoogLenet引數計算方式

  • 經過第一層conv1層(7*7*3),stride為2,padding為3(在這裡是非對稱padding所以才能輸出112*112規格)
    第一層引數計算:7*7*3(卷積核)*64(特徵數量)+64(偏置)=9472=9k
  • 第一層Flops計算(即乘法的次數)
    (7*7*3*64)*112*112=118816768=119M
  • 經過max(3*3,2)層,輸出只與stride與padding有關,所以輸出是56*56*64
  • 經過inception(2)層
    引數計算:(1*1*64)*64+(3*3*64)*192+192=114944=115k
    Flops計算 :
    (1*1*64*64)(引數量)*56*56(輸出圖片規格)+(3*3*64*192)(引數量)*56*56(輸出圖片規格)=360464384=360M
    計算Flops的想法:就是計算所有乘法的數量,就是卷積核的引數乘以特徵數量再乘以圖片的規格(大小)
  • 經過max(3*3,2):同上
  • 經過inception(3a):
    小tips(reduce是指經過1*1卷積核降維之後的特徵數量再經過n*n卷積核計算)
    引數計算:(1*1*192*64)+64(經過1*1卷積核的引數)+(1*1*192*96)+96+(3*3*96*128)+128(經過1*1reduce之後再用3*3卷積核計算)+(1*1*192*16)+16+(5*5*16*32)(5*5卷積核)+1*1*192*32(經過max之後的1*1卷積)=163696=164k
  • 最後一層全連線(FC層):
    引數計算:1024*128=131072=131k
    計算如上所示,剩下的層數的引數都可以計算出來

4 實驗結果

驗證方法

D(xi,xj)是閾值(用L2距離)

Psame(相似影象對),Pdiff(相異影象對)
(True Accept)

TA(d)=(i,j)Psame,withD(xi,xj)d
(False Accept)
FA(d)=(i,j)Pdiff,withD(xi,xj)d VAL(d)=|TA(d)||Psame| FAR(d)=|FA(d)||Pdiff|

1. 不同的網路配置下的識別率

這裡寫圖片描述

2. 不同的影象質量下的識別率

這裡寫圖片描述

3. 不同的特徵維度下的識別率

這裡寫圖片描述

4. 不同的訓練影象資料集的大小

這裡寫圖片描述

5. 對齊的影響

在LFW上,使用了兩種模式:
直接取LFW圖片的中間部分進行訓練,效果98.87%左右。
使用額外的人臉對齊工具,效果99.63%左右,超過deepid。

總結

  1. 新的loss函式(triplet loss)
  2. 特徵維度可以很稀疏128維)(Softmax產生的特徵表示向量都很大,一般超過1000維)
  3. 實驗效果好,在公開的資料集上表現最好(都超過95%)
  4. 需要的預處理比較少,進行分類,直接計算距離就好了,簡單而有效(DeepFace和DeepID需要對齊另外也比PCA + SVM 更加簡單)。