本文主要講centerloss 的原理,及其創新點。然後用caffe 跑自己的數據(CASIA-WebFace | MsCelebV1-Faces-Aligned)
Reference paper:A Discriminative Feature Learning Approach for Deep Face Recognition ECCV:2016
github:https://github.com/ydwen/caffe-face
簡介
一句話:通過添加center loss 讓簡單的softmax 能夠訓練出更有內聚性的特徵。
作者意圖,在配合softmax適用的時候,希望使學習到的特徵具有更好的泛化性和辨別能力。通過懲罰每個種類的樣本和該種類樣本中心的偏移,使得同一種類的樣本儘量聚合在一起。
相對於triplet(Google FaceNet: A Unified Embedding for Face Recognition and Clustering:2015)和contrastive(湯曉鷗Deep LearningFace Representation by
Joint Identification-Verification:2014)來說,這個目標其實相對‘清晰’, 所以網絡收斂的速度甚至比僅僅用softmax更快,而且不需要像前兩者那樣構造大量的訓練對。
我們來看一張圖:
在左圖中,我們發現一個類如果太胖,那麼出現的結果就是類內距離>類間距離。(任意紅點之間的距離應該小於紅藍之間的距離。)
左邊時softmax一般結果,右邊時centerloss結果。我們期望特徵不僅可分,而且時必須差異大。如右邊圖。
centerloss
其中:xi 代表 d 維空間中第 i 個deep feature。屬於第 yi 類。
d——特徵空間的維度。
W——全連接層的參數矩陣。W={d*n}。d行n列。聯想線性分類器 f=Wx+b。
Wj——W的第j 列
m——The size of mini-batch 。
n——and the number of class。
b——偏置。
我們將問題簡化(人不要爲難自己,看一大堆爛公式,還不明白,代個數試試唄)
假設我們的batch=1. 也就是m=1. 數據集就一樣圖片。那麼我們的公式就是簡化成:
我們這個公式是不是非常像softmax function(去掉-log)。參見上一篇博客。
我還是一圖解千言吧:
我們發現,這個softmax的損失僅僅與正確那項的概率相關。
運行截圖:
驗證
在lfw上驗證結果:
這個圖片回答了:batch_size 對於訓練收斂速度有沒有影響。
我們看到bath_size 大的情況下。雖然每次迭代時間消耗比batch_size =70 的時候大。但是batch_size =256的情況下。下降的更加穩健。比較少的出現波動。另外,對於最終的對於測試LFW精確率有一定的影響。
小結
【注】對於深度學習,數據成爲核心,那麼這個實驗的核心也是數據的預處理。
LFW的數據處理應該與CASIA數據集處理方式相同。
其中檢查自己的數據處理方式好不好的一個直接有效的方式是:
【1】LFW中有很多圖片包含多人臉。你的算法是不是裁剪的圖片正中心的那個人?
【2】Alignment做的怎麼樣?很明顯最後一張對齊有問題。
我這裏給大家提供一個已經裁剪好的LFW用來測試:http://pan.baidu.com/s/1kVzA599
宏觀感受
先來看看作者對一個剛從github上拉下來的caffe做了哪些改動。
step1: 修改caffe.proto
vim caffe/src/caffe/proto/caffe.proto
圖爲未修改之前LayerParameter的配置
// 1-修改如下注釋
//Update the next available ID when you add a new LayerParameter field
//LayerParameter next available layer-specific ID: 148 (last added: center_loss_param)
//其中148 這個數字得注意。 caffe的LayerParameter中新定義下一個變量的ID:147. 我們新加入一個變量後,下一個新加入的變量ID:148.
// 2-添加如下代碼 在LayerParameter中
optional CenterLossParameter center_loss_param = 147;
// 3-在caffe.proto 最末尾添加自己定義層
message CenterLossParameter {
optional uint32 num_output = 1; // The number of outputs for the layer
optional FillerParameter center_filler = 2; // The filler for the centers
optional int32 axis = 3 [default = 1]; //default = 1 相當於c++總的缺省初始化值。
}
/* 標籤數字1和2,3表示不同的字段在序列化後的二進制數據中的佈局位置。在該例中,center_filler字段編碼後的數據一定位於num_output後。需要注意的是該值在同一message中不能重複。*/
// 說白了,1,2,3代表了他們編碼之後的順序,小號在前,大號在後。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
最近一週會更新完畢!!