在深度學(xué)習(xí)出現(xiàn)后,人臉識(shí)別技術(shù)才真正有了可用性。這是因?yàn)橹暗臋C(jī)器學(xué)習(xí)技術(shù)中,難以從圖片中取出合適的特征值。輪廓?顏色?眼睛?如此多的面孔,且隨著年紀(jì)、光線、拍攝角度、氣色、表情、化妝、佩飾掛件等等的不同,同一個(gè)人的面孔照片在照片象素層面上差別很大,憑借專家們的經(jīng)驗(yàn)與試錯(cuò)難以取出準(zhǔn)確率較高的特征值,自然也沒法對(duì)這些特征值進(jìn)一步分類。深度學(xué)習(xí)的最大優(yōu)勢(shì)在于由訓(xùn)練算法自行調(diào)整參數(shù)權(quán)重,構(gòu)造出一個(gè)準(zhǔn)確率較高的f(x)函數(shù),給定一張照片則可以獲取到特征值,進(jìn)而再歸類。
本文中筆者試圖用通俗的語言探討人臉識(shí)別技術(shù),首先概述人臉識(shí)別技術(shù),接著探討深度學(xué)習(xí)有效的原因以及梯度下降為什么可以訓(xùn)練出合適的權(quán)重參數(shù),最后描述基于CNN卷積神經(jīng)網(wǎng)絡(luò)的人臉識(shí)別。
人臉識(shí)別技術(shù)大致由人臉檢測(cè)和人臉識(shí)別兩個(gè)環(huán)節(jié)組成。
之所以要有人臉檢測(cè),不光是為了檢測(cè)出照片上是否有人臉,更重要的是把照片中人臉無關(guān)的部分刪掉,否則整張照片的像素都傳給f(x)識(shí)別函數(shù)肯定就不可用了。人臉檢測(cè)不一定會(huì)使用深度學(xué)習(xí)技術(shù),因?yàn)檫@里的技術(shù)要求相對(duì)低一些,只需要知道有沒有人臉以及人臉在照片中的大致位置即可。一般我們考慮使用OpenCV、dlib等開源庫的人臉檢測(cè)功能(基于專家經(jīng)驗(yàn)的傳統(tǒng)特征值方法計(jì)算量少從而速度更快),也可以使用基于深度學(xué)習(xí)實(shí)現(xiàn)的技術(shù)如MTCNN(在神經(jīng)網(wǎng)絡(luò)較深較寬時(shí)運(yùn)算量大從而慢一些)。
在人臉檢測(cè)環(huán)節(jié)中,我們主要關(guān)注檢測(cè)率、漏檢率、誤檢率三個(gè)指標(biāo),其中:
? 檢測(cè)率:存在人臉并且被檢測(cè)出的圖像在所有存在人臉圖像中的比例;? 漏檢率:存在人臉但是沒有檢測(cè)出的圖像在所有存在人臉圖像中的比例;? 誤檢率:不存在人臉但是檢測(cè)出存在人臉的圖像在所有不存在人臉圖像中的比例。
當(dāng)然,檢測(cè)速度也很重要。本文不對(duì)人臉檢測(cè)做進(jìn)一步描述。
在人臉識(shí)別環(huán)節(jié),其應(yīng)用場(chǎng)景一般分為1:1和1:N。
1:1就是判斷兩張照片是否為同一個(gè)人,通常應(yīng)用在人證匹配上,例如身份證與實(shí)時(shí)抓拍照是否為同一個(gè)人,常見于各種營業(yè)廳以及后面介紹的1:N場(chǎng)景中的注冊(cè)環(huán)節(jié)。而1:N應(yīng)用場(chǎng)景,則是首先執(zhí)行注冊(cè)環(huán)節(jié),給定N個(gè)輸入包括人臉照片以及其ID標(biāo)識(shí),再執(zhí)行識(shí)別環(huán)節(jié),給定人臉照片作為輸入,輸出則是注冊(cè)環(huán)節(jié)中的某個(gè)ID標(biāo)識(shí)或者不在注冊(cè)照片中??梢?從概率角度上來看,前者相對(duì)簡單許多,且由于證件照通常與當(dāng)下照片年代間隔時(shí)間不定,所以通常我們?cè)O(shè)定的相似度閾值都是比較低的,以此獲得比較好的通過率,容忍稍高的誤識(shí)別率。
而后者1:N,隨著N的變大,誤識(shí)別率會(huì)升高,識(shí)別時(shí)間也會(huì)增長,所以相似度閾值通常都設(shè)定得較高,通過率會(huì)下降。這里簡單解釋下上面的幾個(gè)名詞:誤識(shí)別率就是照片其實(shí)是A的卻識(shí)別為B的比率;通過率就是照片確實(shí)是A的,但可能每5張A的照片才能識(shí)別出4張是A其通過率就為80%;相似度閾值是因?yàn)閷?duì)特征值進(jìn)行分類是概率行為,除非輸入的兩張照片其實(shí)是同一個(gè)文件,否則任何兩張照片之間都有一個(gè)相似度,設(shè)定好相似度閾值后唯有兩張照片的相似度超過閾值,才認(rèn)為是同一個(gè)人。所以,單純的評(píng)價(jià)某個(gè)人臉識(shí)別算法的準(zhǔn)確率沒有意義,我們最需要弄清楚的是誤識(shí)別率小于某個(gè)值時(shí)(例如0.1%)的通過率。不管1:1還是1:N,其底層技術(shù)是相同的,只是難度不同而已。
取出人臉特征值是最難的,那么深度學(xué)習(xí)是如何取特征值的?
假定我們給出的人臉照片是100*100像素大小,由于每個(gè)像素有RGB三個(gè)通道,每個(gè)像素通道由0-255范圍的字節(jié)表示,則共有3個(gè)100*100的矩陣計(jì)3萬個(gè)字節(jié)作為輸入數(shù)據(jù)。深度學(xué)習(xí)實(shí)際上就是生成一個(gè)近似函數(shù),把上面的輸入值轉(zhuǎn)化為可以用作特征分類的特征值。那么,特征值可以是一個(gè)數(shù)字嗎?當(dāng)然不行,一個(gè)數(shù)字(或者叫標(biāo)量)是無法有效表示出特征的。通常我們用多個(gè)數(shù)值組成的向量表示特征值,向量的維度即其中的數(shù)值個(gè)數(shù)。特征向量的維度并非越大越好,Google的FaceNet項(xiàng)目(參見https://arxiv.org/abs/1503.03832論文)做過的測(cè)試結(jié)果顯示,128個(gè)數(shù)值組成的特征向量結(jié)果最好,如下圖所示:
那么,現(xiàn)在問題就轉(zhuǎn)化為怎么把3*100*100的矩陣轉(zhuǎn)化為128維的向量,且這個(gè)向量能夠準(zhǔn)確的區(qū)分出不同的人臉?
假定照片為x,特征值為y,也就是說存在一個(gè)函數(shù)f(x)=y可以完美的找出照片的人臉特征值。現(xiàn)在我們有一個(gè)f*(x)近似函數(shù),其中它有參數(shù)w(或者叫權(quán)重w)可以設(shè)置,例如寫成f*(x;w),若有訓(xùn)練集x及其id標(biāo)識(shí)y,設(shè)初始參數(shù)p1后,那么每次f*(x;w)得到的y`與實(shí)際標(biāo)識(shí)y相比,若正確則通過,若錯(cuò)誤則適當(dāng)調(diào)整參數(shù)w,如果能夠正確的調(diào)整好參數(shù)w,f*(x;w)就會(huì)與理想中的f(x)函數(shù)足夠接近,我們就獲得了概率上足夠高準(zhǔn)確率的f*(x;w)函數(shù)。這一過程叫做監(jiān)督學(xué)習(xí)下的訓(xùn)練。而計(jì)算f*(x;w)值的過程因?yàn)槭钦5暮瘮?shù)運(yùn)算,我們稱為前向運(yùn)算,而訓(xùn)練過程中比較y`與實(shí)際標(biāo)識(shí)id值y結(jié)果后,調(diào)整參數(shù)p的過程則是反過來的,稱為反向傳播。
由于我們傳遞的x入?yún)吘故且粡堈掌?照片既有對(duì)焦、光線、角度等導(dǎo)致的不太容易衡量的質(zhì)量問題,也有本身的像素?cái)?shù)多少問題。如果x本身含有的數(shù)據(jù)太少,即圖片非常不清晰,例如28*28像素的照片,那么誰也無法準(zhǔn)確的分辨出是哪個(gè)人。可以想見,必然像素?cái)?shù)越多識(shí)別也越準(zhǔn),但像素?cái)?shù)越多導(dǎo)致的計(jì)算、傳輸、存儲(chǔ)消耗也越大,我們需要有根據(jù)地找到合適的閾值。下圖是FaceNet論文的結(jié)果,雖然只是一家之言,但Google的嚴(yán)謹(jǐn)態(tài)度使得數(shù)據(jù)也很有參考價(jià)值。
從圖中可見,排除照片其他質(zhì)量外,像素?cái)?shù)至少也要有100*100(純?nèi)四槻糠?才能保證比較高的識(shí)別率。
由清晰的人臉照轉(zhuǎn)化出的像素值矩陣,應(yīng)當(dāng)設(shè)計(jì)出什么樣的函數(shù)f(x)轉(zhuǎn)化為特征值呢?這個(gè)問題的答案依賴于分類問題。即,先不談特征值,首先如何把照片集合按人正確地分類?這里就要先談?wù)剻C(jī)器學(xué)習(xí)。機(jī)器學(xué)習(xí)認(rèn)為可以從有限的訓(xùn)練集樣本中把算法很好地泛化。所以,我們先找到有限的訓(xùn)練集,設(shè)計(jì)好初始函數(shù)f(x;w),并已經(jīng)量化好了訓(xùn)練集中x->y。如果數(shù)據(jù)x是低維的、簡單的,例如只有二維,那么分類很簡單,如下圖所示:
上圖中的二維數(shù)據(jù)x只有方形和圓形兩個(gè)類別y,很好分,我們需要學(xué)習(xí)的分類函數(shù)用最簡單的f(x,y)=ax+by+c就能表示出分類直線。例如f(x,y)大于0時(shí)表示圓形,小于0時(shí)表示方形。
給定隨機(jī)數(shù)作為a,c,b的初始值,我們通過訓(xùn)練數(shù)據(jù)不斷的優(yōu)化參數(shù)a,b,c,把不合適的L1、L3等分類函數(shù)逐漸訓(xùn)練成L2,這樣的L2去面對(duì)泛化的測(cè)試數(shù)據(jù)就可能獲得更好的效果。然而如果有多個(gè)類別,就需要多條分類直線才能分出,如下圖所示:
這其實(shí)相當(dāng)于多條分類函數(shù)執(zhí)行與&&、或||操作后的結(jié)果。這個(gè)時(shí)候還可能用f1>0 && f2<0 && f3>0這樣的分類函數(shù),但如果更復(fù)雜的話,例如本身的特征不明顯也沒有匯聚在一起,這種找特征的方式就玩不轉(zhuǎn)了,如下圖所示,不同的顏色表示不同的分類,此時(shí)的訓(xùn)練數(shù)據(jù)完全是非線性可分的狀態(tài):
這個(gè)時(shí)候,我們可以通過多層函數(shù)嵌套的方法來解決,例如f(x)=f1(f2(x)),這樣f2函數(shù)可以是數(shù)條直線,而f1函數(shù)可以通過不同的權(quán)重w以及激勵(lì)函數(shù)完成與&&、或||等等操作。這里只有兩層函數(shù),如果函數(shù)嵌套層數(shù)越多,它越能表達(dá)出復(fù)雜的分類方法,這對(duì)高維數(shù)據(jù)很有幫助。例如我們的照片毫無疑問就是這樣的輸入。所謂激勵(lì)函數(shù)就是把函數(shù)f計(jì)算出的非常大的值域轉(zhuǎn)化為[0,1]這樣較小的值域,這允許多層函數(shù)不斷地前向運(yùn)算、分類。
前向運(yùn)算只是把輸入交給f1(x,w1)函數(shù),計(jì)算出的值再交給f2(y1,w2)函數(shù),依次類推,很簡單就可以得到最終的分類值。但是,因?yàn)槌跏嫉膚權(quán)重其實(shí)沒有多大意義,它得出的分類值f*(x)肯定是錯(cuò)的,在訓(xùn)練集上我們知道正確的值y,那么事實(shí)上我們其實(shí)是希望y-f*(x)的值最小,這樣分類就越準(zhǔn)。這其實(shí)變成了求最小值的問題。當(dāng)然,y-f*(x)只是示意,事實(shí)上我們得到的f*(x)只是落到各個(gè)分類上的概率,把這個(gè)概率與真實(shí)的分類相比較得到最小值的過程,我們稱為損失函數(shù),其值為loss,我們的目標(biāo)是把損失函數(shù)的值loss最小化。在人臉識(shí)別場(chǎng)景中,softmax是一個(gè)效果比較好的損失函數(shù),我們簡單看下它是如何使用的。
比如我們有訓(xùn)練數(shù)據(jù)集照片對(duì)應(yīng)著cat、dog、ship三個(gè)類別,某個(gè)輸入照片經(jīng)過函數(shù)f(x)=x*W+b,前向運(yùn)算得到該照片屬于這3個(gè)分類的得分值。此時(shí),這個(gè)函數(shù)被稱為得分函數(shù),如下圖所示,假設(shè)左邊關(guān)于貓的input image是一個(gè)4維向量[56,231,24,2],而W權(quán)重是一個(gè)4*3的矩陣,那么相乘后再加上向量[1.1,3.2,-1.2]可得到在cat、 dog、ship三個(gè)類別上的得分:
從上圖示例可見,雖然輸入照片是貓,但得分上屬于狗的得分值437.9最高,但究竟比貓和船高多少呢?很難衡量!如果我們把得分值轉(zhuǎn)化為0-100的百分比概率,這就方便度量了。這里我們可以使用sigmoid函數(shù),如下圖所示:
從上圖公式及圖形可知,sigmoid可以把任意實(shí)數(shù)轉(zhuǎn)換為0-1之間的某個(gè)數(shù)作為概率。但sigmoid概率不具有歸一性,也就是說我們需要保證輸入照片在所有類別的概率之和為1,這樣我們還需要對(duì)得分值按softmax方式做以下處理:
這樣給定x后可以得到x在各個(gè)類別下的概率。假定三個(gè)類別的得分值分別為3、1、-3,則按照上面的公式運(yùn)算后可得概率分別為[0.88、0.12、0],計(jì)算過程如下圖所示:
然而實(shí)際上x對(duì)應(yīng)的概率其實(shí)是第一類,比如[1,0,0],現(xiàn)在拿到的概率(或者可稱為似然)是[0.88、0.12、0]。那么它們之間究竟有多大的差距呢?這個(gè)差距就是損失值loss。如何獲取到損失值呢?在softmax里我們用互熵?fù)p失函數(shù)計(jì)算量最小(方便求導(dǎo)),如下所示:
其中i就是正確的分類,例如上面的例子中其loss值就是-ln0.88。這樣我們有了損失函數(shù)f(x)后,怎么調(diào)整x才能夠使得函數(shù)的loss值最小呢?這涉及到微分導(dǎo)數(shù)。
梯度下降就是為了快速的調(diào)整權(quán)重w,使得損失函數(shù)f(x;w)的值最小。因?yàn)閾p失函數(shù)的值loss最小,就表示上面所說的在訓(xùn)練集上的得分結(jié)果與正確的分類值最接近!
導(dǎo)數(shù)求的是函數(shù)在某一點(diǎn)上的變化率。例如從A點(diǎn)開車到B點(diǎn),通過距離和時(shí)間可以算出平均速度,但在其中C點(diǎn)的瞬時(shí)速度是多少呢?如果用x表示時(shí)間,f(x)表示車子從A點(diǎn)駛出的距離,那么在x0的瞬時(shí)速度可以轉(zhuǎn)化為:從x0時(shí)再開一個(gè)很小的時(shí)間,例如1秒,那么這一秒的平均速度就是這一秒開出的距離除以1秒,即(f(1+x0)-f(x0))/1。如果我們用的不是1秒而是1微秒,那么這個(gè)1微秒內(nèi)的平均速度必然更接近x0時(shí)的瞬時(shí)速度。于是,到該時(shí)間段t趨向于0時(shí),我們就得到了x0時(shí)的瞬時(shí)速度。這個(gè)瞬時(shí)速度就是函數(shù)f在x0上的變化率,所有x上的變化率就構(gòu)成了函數(shù)f(x)的導(dǎo)數(shù),稱為f`(x)。即:
從幾何意義上看,變化率就變成了斜率,這更容易理解怎樣求函數(shù)的最小值。例如下圖中有函數(shù)y=f(x)用粗體黑線表示,其在P0點(diǎn)的變化率就是切線紅線的斜率:
可以形象的看出,當(dāng)斜率的值為正數(shù)時(shí),把x向左移動(dòng)變小一些,f(x)的值就會(huì)小一些;當(dāng)斜率的值為負(fù)數(shù)時(shí),把x向右移動(dòng)變大一些,f(x)的值也會(huì)小一些,如下圖所示:
這樣,斜率為0時(shí)我們其實(shí)就得到了函數(shù)f在該點(diǎn)可以得到最小值。那么,把x向左或者向右移一點(diǎn),到底移多少呢?如果移多了,可能移過了,如果移得很少,則可能要移很久才能找到最小點(diǎn)。還有一個(gè)問題,如果f(x)操作函數(shù)有多個(gè)局部最小點(diǎn)、全局最小點(diǎn)時(shí),如果x移的非常小,則可能導(dǎo)致通過導(dǎo)數(shù)只能找到某個(gè)并不足夠小的局部最小點(diǎn)。如下圖所示:
藍(lán)色的為局部最小點(diǎn),紅色是全局最小點(diǎn)。所以x移動(dòng)多少是個(gè)問題,x每次的移動(dòng)步長過大或者過小都可能導(dǎo)致找不到全局最小點(diǎn)。這個(gè)步長除了跟導(dǎo)數(shù)斜率有關(guān)外,我們還需要有一個(gè)超參數(shù)來控制它的移動(dòng)速度,這個(gè)超參數(shù)稱為學(xué)習(xí)率,由于它很難優(yōu)化,所以一般需要手動(dòng)設(shè)置而不能自動(dòng)調(diào)整。考慮到訓(xùn)練時(shí)間也是成本,我們通常在初始訓(xùn)練階段把學(xué)習(xí)率設(shè)的大一些,越往后學(xué)習(xí)率設(shè)的越小。
那么每次移動(dòng)的步長與導(dǎo)數(shù)的值有關(guān)嗎?這是自然的,導(dǎo)數(shù)的正負(fù)值決定了移動(dòng)的方向,而導(dǎo)數(shù)的絕對(duì)值大小則決定了斜率是否陡峭。越陡峭則移動(dòng)的步長應(yīng)當(dāng)越大。所以,步長由學(xué)習(xí)率和導(dǎo)數(shù)共同決定。就像下面這個(gè)函數(shù),λ是學(xué)習(xí)率,而?F(ωj) / ?ωj是在ωj點(diǎn)的導(dǎo)數(shù)。
ωj = ωj – λ ?F(ωj) / ?ωj
根據(jù)導(dǎo)數(shù)判斷損失函數(shù)f在x0點(diǎn)上應(yīng)當(dāng)如何移動(dòng),才能使得f最快到達(dá)最小值的方法,我們稱為梯度下降。梯度也就是導(dǎo)數(shù),沿著負(fù)梯度的方向,按照梯度值控制移動(dòng)步長,就能快速到達(dá)最小值。當(dāng)然,實(shí)際上我們未必能找到最小點(diǎn),特別是本身存在多個(gè)最小點(diǎn)時(shí),但如果這個(gè)值本身也足夠小,我們也是可以接受的,如下圖所示:
以上我們是以一維數(shù)據(jù)來看梯度下降,但我們的照片是多維數(shù)據(jù),此時(shí)如何求導(dǎo)數(shù)?又如何梯度下降呢?此時(shí)我們需要用到偏導(dǎo)數(shù)的概念。其實(shí)它與導(dǎo)數(shù)很相似,因?yàn)閤是多維向量,那么我們假定計(jì)算Xi的導(dǎo)數(shù)時(shí),x上的其他數(shù)值不變,這就是Xi的偏導(dǎo)數(shù)。此時(shí)應(yīng)用梯度下降法就如下圖所示,θ是二維的,我們分別求θ0和θ1的導(dǎo)數(shù),就可以同時(shí)從θ0和θ1兩個(gè)方向移動(dòng)相應(yīng)的步長,尋找最低點(diǎn),如下圖所示:
前文說過,根據(jù)有限的訓(xùn)練集,去適應(yīng)無限的測(cè)試集,當(dāng)然訓(xùn)練集容量越大效果就越好。但是,訓(xùn)練集如果很大,那么每次都根據(jù)全部數(shù)據(jù)執(zhí)行梯度下降計(jì)算量就太大了。此時(shí),我們選擇每次只取全部訓(xùn)練集中的一小部分(究竟多少,一般根據(jù)內(nèi)存和計(jì)算量而定),執(zhí)行梯度下降,不斷的迭代,根據(jù)經(jīng)驗(yàn)一樣可以快速地把梯度降下來。這就是隨機(jī)梯度下降。
上面的梯度下降法只能對(duì)f函數(shù)的w權(quán)重進(jìn)行調(diào)整,而上文中我們說過實(shí)際是多層函數(shù)套在一起,例如f1(f2(x;w2);w1),那么怎么求對(duì)每一層函數(shù)輸入的導(dǎo)數(shù)呢?這也是所謂的反向傳播怎樣繼續(xù)反向傳遞下去呢?這就要提到鏈?zhǔn)椒▌t。其實(shí)質(zhì)為,本來y對(duì)x的求導(dǎo),可以通過引入中間變量z來實(shí)現(xiàn),如下圖所示:
這樣,y對(duì)x的導(dǎo)數(shù)等價(jià)于y對(duì)z的導(dǎo)數(shù)乘以z對(duì)x的偏導(dǎo)。當(dāng)輸入為多維時(shí)則有下面的公式:
如此,我們可以得到每一層函數(shù)的導(dǎo)數(shù),這樣可以得到每層函數(shù)的w權(quán)重應(yīng)當(dāng)調(diào)整的步長,優(yōu)化權(quán)重參數(shù)。
由于函數(shù)的導(dǎo)數(shù)很多,例如resnet等網(wǎng)絡(luò)已經(jīng)達(dá)到100多層函數(shù),所以為區(qū)別傳統(tǒng)的機(jī)器學(xué)習(xí),我們稱其為深度學(xué)習(xí)。
深度學(xué)習(xí)只是受到神經(jīng)科學(xué)的啟發(fā),所以稱為神經(jīng)網(wǎng)絡(luò),但實(shí)質(zhì)上就是上面提到的多層函數(shù)前向運(yùn)算得到分類值,訓(xùn)練時(shí)根據(jù)實(shí)際標(biāo)簽分類取損失函數(shù)最小化后,根據(jù)隨機(jī)梯度下降法來優(yōu)化各層函數(shù)的權(quán)重參數(shù)。人臉識(shí)別也是這么一個(gè)流程。以上我們初步過完多層函數(shù)的參數(shù)調(diào)整,但函數(shù)本身應(yīng)當(dāng)如何設(shè)計(jì)呢?
我們先從全連接網(wǎng)絡(luò)談起。Google的TensorFlow游樂場(chǎng)里可以直觀的體驗(yàn)全連接神經(jīng)網(wǎng)絡(luò)的威力,這是游樂場(chǎng)的網(wǎng)址:http://playground.tensorflow.org/,瀏覽器里就可以做神經(jīng)網(wǎng)絡(luò)訓(xùn)練,且過程與結(jié)果可視化。如下圖所示:
這個(gè)神經(jīng)網(wǎng)絡(luò)游樂場(chǎng)共有1000個(gè)訓(xùn)練點(diǎn)和1000個(gè)測(cè)試點(diǎn),用于對(duì)4種不同圖案劃分出藍(lán)色點(diǎn)與黃色點(diǎn)。DATA處可選擇4種不同圖案。
整個(gè)網(wǎng)絡(luò)的輸入層是FEATURES(待解決問題的特征),例如x1和x2表示垂直或者水平切分來劃分藍(lán)色與黃色點(diǎn),這是最容易理解的2種劃分點(diǎn)的方法。其余5種其實(shí)不太容易想到,這也是傳統(tǒng)的專家系統(tǒng)才需要的,實(shí)際上,這個(gè)游樂場(chǎng)就是為了演示,1、好的神經(jīng)網(wǎng)絡(luò)只用最基本的x1,x2這樣的輸入層FEATURES就可以完美的實(shí)現(xiàn);2、即使有很多種輸入特征,我們其實(shí)并不清楚誰的權(quán)重最高,但好的神經(jīng)網(wǎng)絡(luò)會(huì)解決掉這個(gè)問題。
隱層(HIDDEN LAYERS)可以隨意設(shè)置層數(shù),每個(gè)隱層可以設(shè)置神經(jīng)元數(shù)。實(shí)際上神經(jīng)網(wǎng)絡(luò)并不是在計(jì)算力足夠的情況下,層數(shù)越多越好或者每層神經(jīng)元越多越好。好的神經(jīng)網(wǎng)絡(luò)架構(gòu)模型是很難找到的。本文后面我們會(huì)重點(diǎn)講幾個(gè)CNN經(jīng)典網(wǎng)絡(luò)模型。然而,在這個(gè)例子中,多一些隱層和神經(jīng)元可以更好地劃分。
epoch是訓(xùn)練的輪數(shù)。紅色框出的loss值是衡量訓(xùn)練結(jié)果的最重要指標(biāo),如果loss值一直是在下降,比如可以低到0.01這樣,就說明這個(gè)網(wǎng)絡(luò)訓(xùn)練的結(jié)果好。loss也可能下降一會(huì)又突然上升,這就是不好的網(wǎng)絡(luò),大家可以嘗試下。learning rate初始都會(huì)設(shè)得高些,訓(xùn)練到后面都會(huì)調(diào)低些。Activation是激勵(lì)函數(shù),目前CNN都在使用Relu函數(shù)。
了解了神經(jīng)網(wǎng)絡(luò)后,現(xiàn)在我們回到人臉識(shí)別中來。每一層神經(jīng)元就是一個(gè)f函數(shù),上面的四層網(wǎng)絡(luò)就是f1(f2(f3(f4(x))))。然而,就像上文所說,照片的像素太多了,全連接網(wǎng)絡(luò)中任意兩層之間每兩個(gè)神經(jīng)元都需要有一次計(jì)算。特別之前提到的,復(fù)雜的分類依賴于許多層函數(shù)共同運(yùn)算才能達(dá)到目的。當(dāng)前的許多網(wǎng)絡(luò)都是多達(dá)100層以上,如果每層都有3*100*100個(gè)神經(jīng)元,可想而知計(jì)算量有多大!于是CNN卷積神經(jīng)網(wǎng)絡(luò)應(yīng)運(yùn)而生,它可以在大幅降低運(yùn)算量的同時(shí)保留全連接網(wǎng)絡(luò)的威力。
CNN認(rèn)為可以只對(duì)整張圖片的一個(gè)矩形窗口做全連接運(yùn)算(可稱為卷積核),滑動(dòng)這個(gè)窗口以相同的權(quán)重參數(shù)w遍歷整張圖片后,可以得到下一層的輸入,如下圖所示:
CNN中認(rèn)為同一層中的權(quán)重參數(shù)可以共享,因?yàn)橥粡垐D片的各個(gè)不同區(qū)域具有一定的相似性。這樣原本的全連接計(jì)算量過大問題就解決了,如下圖所示:
結(jié)合著之前的函數(shù)前向運(yùn)算與矩陣,我們以一個(gè)動(dòng)態(tài)圖片直觀的看一下前向運(yùn)算過程:
這里卷積核大小與移動(dòng)的步長stride、輸出深度決定了下一層網(wǎng)絡(luò)的大小。同時(shí),核大小與stride步長在導(dǎo)致上一層矩陣不夠大時(shí),需要用padding來補(bǔ)0(如上圖灰色的0)。以上就叫做卷積運(yùn)算,這樣的一層神經(jīng)元稱為卷積層。上圖中W0和W1表示深度為2。
CNN卷積網(wǎng)絡(luò)通常在每一層卷積層后加一個(gè)激勵(lì)層,激勵(lì)層就是一個(gè)函數(shù),它把卷積層輸出的數(shù)值以非線性的方式轉(zhuǎn)換為另一個(gè)值,在保持大小關(guān)系的同時(shí)約束住值范圍,使得整個(gè)網(wǎng)絡(luò)能夠訓(xùn)練下去。在人臉識(shí)別中,通常都使用Relu函數(shù)作為激勵(lì)層,Relu函數(shù)就是max(0,x),如下所示:
可見 Relu的計(jì)算量其實(shí)非常小!
CNN中還有一個(gè)池化層,當(dāng)某一層輸出的數(shù)據(jù)量過大時(shí),通過池化層可以對(duì)數(shù)據(jù)降維,在保持住特征的情況下減少數(shù)據(jù)量,例如下面的4*4矩陣通過取最大值降維到2*2矩陣:
上圖中通過對(duì)每個(gè)顏色塊篩選出最大數(shù)字進(jìn)行池化,以減小計(jì)算數(shù)據(jù)量。
通常網(wǎng)絡(luò)的最后一層為全連接層,這樣一般的CNN網(wǎng)絡(luò)結(jié)構(gòu)如下所示:
CONV就是卷積層,每個(gè)CONV后會(huì)攜帶RELU層。這只是一個(gè)示意圖,實(shí)際的網(wǎng)絡(luò)要復(fù)雜許多。目前開源的Google FaceNet是采用resnet v1網(wǎng)絡(luò)進(jìn)行人臉識(shí)別的,關(guān)于resnet網(wǎng)絡(luò)請(qǐng)參考論文https://arxiv.org/abs/1602.07261,其完整的網(wǎng)絡(luò)較為復(fù)雜,這里不再列出,也可以查看基于TensorFlow實(shí)現(xiàn)的Python代碼https://github.com/davidsandberg/facenet/blob/master/src/models/inception_resnet_v1.py,注意slim.conv2d含有Relu激勵(lì)層。
以上只是通用的CNN網(wǎng)絡(luò),由于人臉識(shí)別應(yīng)用中不是直接分類,而是有一個(gè)注冊(cè)階段,需要把照片的特征值取出來。如果直接拿softmax分類前的數(shù)據(jù)作為特征值效果很不好,例如下圖是直接將全連接層的輸出轉(zhuǎn)化為二維向量,在二維平面上通過顏色表示分類的可視化表示:
可見效果并不好,中間的樣本距離太近了。通過centor loss方法處理后,可以把特征值間的距離擴(kuò)大,如下圖所示:
這樣取出的特征值效果就會(huì)好很多。
實(shí)際訓(xùn)練resnet v1網(wǎng)絡(luò)時(shí),首先需要關(guān)注訓(xùn)練集照片的質(zhì)量,且要把不同尺寸的人臉照片resize到resnet1網(wǎng)絡(luò)首層接收的尺寸大小。另外除了上面提到的學(xué)習(xí)率和隨機(jī)梯度下降中每一批batchsize圖片的數(shù)量外,還需要正確的設(shè)置epochsize,因?yàn)槊恳惠唀poch應(yīng)當(dāng)完整的遍歷完訓(xùn)練集,而batchsize受限于硬件條件一般不變,但訓(xùn)練集可能一直在變大,這樣應(yīng)保持epochsize*batchsize接近全部訓(xùn)練集。訓(xùn)練過程中需要密切關(guān)注loss值是否在收斂,可適當(dāng)調(diào)節(jié)學(xué)習(xí)率。
最后說一句,目前人臉識(shí)別效果的評(píng)價(jià)唯一通行的標(biāo)準(zhǔn)是LFW(即Labeled Faces in the Wild),它包含大約6000個(gè)不同的人的12000張照片,許多算法都依據(jù)它來評(píng)價(jià)準(zhǔn)確率。但它有兩個(gè)問題,一是數(shù)據(jù)集不夠大,二是數(shù)據(jù)集場(chǎng)景往往與真實(shí)應(yīng)用場(chǎng)景并不匹配。所以如果某個(gè)算法稱其在LFW上的準(zhǔn)確率達(dá)到多么的高,并不能反應(yīng)其真實(shí)可用性。
原文標(biāo)題:深入淺出談人臉識(shí)別技術(shù)
文章出處:【微信號(hào):Imgtec,微信公眾號(hào):Imagination Tech】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。