cascade down_Cascaded CNN 方法寻找人脸关键点
Cascaded CNN 方法尋找人臉關(guān)鍵點(diǎn)
論文筆記
閱讀論文
第一階段閱讀論文,大約兩天大體閱讀完論文 Deep Convolutional Network Cascade for Facial Point Detection。感覺還是比較缺乏論文閱讀經(jīng)驗(yàn),但是比以前快了很多。主要閱讀論文 intro、method 和 modeling。作者的思維比較奇特,把損失函數(shù)放在 experiment 部分,我找了好久沒找到。
編寫代碼
尋找同學(xué)幫助,發(fā)現(xiàn)代碼變化太快,舊經(jīng)驗(yàn)有些跟不上。嘗試瞎貓撞死耗子的策略,瞎寫,顯然不能成功,浪費(fèi) 4+ 天時(shí)間。
靜下心,閱讀 Caffe 框架代碼,C++ 不熟悉,讀 C++ 代碼沒經(jīng)驗(yàn)。硬著頭皮讀,不得法,痛苦,事倍功半;晚上,腦子突然靈光一閃,讀繼承關(guān)系和頭文件(因?yàn)?C 的頭文件只是函數(shù)聲明,而宏定義可以臨時(shí)找),有效,思路清晰。一天時(shí)間寫完代碼。
NaN 和收斂失敗
計(jì)算結(jié)果 J(theta) 是 NaN,天!各種 Debug,找了 3+ 天,代碼中沒發(fā)現(xiàn)和數(shù)值相關(guān)的 BUG。也許是數(shù)值計(jì)算方法的問題?不能,這是框架寫的代碼。后來發(fā)是學(xué)習(xí)率調(diào)太大。之前已經(jīng)調(diào)小過,無效,沒想到還要繼續(xù)調(diào)小。
再次驗(yàn)證,收斂失敗。這是什么原因?后來發(fā)現(xiàn)是 loss 的設(shè)計(jì)存在問題,沒有做 normalization。細(xì)節(jié)在這里。收斂成功。
算法效果驗(yàn)證
最直接的方法當(dāng)然是輸出坐標(biāo)點(diǎn),可惜一點(diǎn)都不直觀。寫了一堆代碼用來在圖上做各種標(biāo)記,代碼混亂成翔(后來抽取到 我的 github)。從輸出來看,總體位置還算靠譜,但是效果并不好,雖然還沒量化,但是我知道肯定不好,不用算了。
我天真的覺得是 overfit 了。在 train set 做個(gè)測(cè)試,underfit。
突然想到會(huì)不會(huì)是 BUG 導(dǎo)致所有輸出都是一樣的?檢查了輸出的坐標(biāo),雖然比較相近,但是確實(shí)是不同的,所以應(yīng)該不是 BUG。這說明,沒有提取到足夠的 inter-face 特征?這個(gè)地方要想想。
單點(diǎn)驗(yàn)證
其實(shí)我沒有完全按照論文實(shí)現(xiàn)。論文結(jié)構(gòu)太復(fù)雜,存在 3 個(gè)級(jí)聯(lián),第一個(gè)級(jí)聯(lián)有 3 個(gè)網(wǎng)絡(luò)做平均。作者的說法是第一個(gè)級(jí)聯(lián)最重要,所以我只實(shí)現(xiàn)了第一個(gè)級(jí)聯(lián)的其中一個(gè)網(wǎng)絡(luò)。有可能沒有完全按照結(jié)構(gòu)設(shè)計(jì)導(dǎo)致的問題?
另外一個(gè)思路是,用一個(gè) kernel 去掃描 5 個(gè)不同的面部特征真的靠譜么?我也許試試五個(gè) kernel?一時(shí)間沒有思路為何 underfit。先做一個(gè) left eye 試試吧。我快速 10000 輪迭代做出個(gè) model,輸出一百個(gè)圖像來人力比較,第一印象是單點(diǎn)的確比多點(diǎn)要準(zhǔn)確??匆幌?lián)p失:
左眼坐標(biāo)網(wǎng)絡(luò)損失:I0920 16:27:52.355422 11912 solver.cpp:294] Iteration 10000, Testing net (#0)
I0920 16:27:52.606781 11912 solver.cpp:343] Test net output #0: loss = 0.00317065 (* 1 = 0.00317065 loss)
臉部坐標(biāo)網(wǎng)絡(luò)損失:I0920 16:19:16.628931 48513 solver.cpp:294] Iteration 10000, Testing net (#0)
I0920 16:19:16.885615 48513 solver.cpp:343] Test net output #0: loss = 0.0263838 (* 1 = 0.0263838 loss)
從數(shù)據(jù)來看,確實(shí)只做一個(gè)坐標(biāo)效果會(huì)比較好。
重讀論文
我想我一定是弄錯(cuò)論文某些細(xì)節(jié)了,我決定重新讀一遍這篇論文。重新閱讀論文過程中,我產(chǎn)生了新的想法。
之前的 network 只有一個(gè) kernel,而作者提出的方案是 locally weight-sharing,開始的時(shí)候不甚明了,直接忽略了。我看了 Convolutional Neural Networks 突然想通了 weight-sharing 指的是什么意思。Convolutional layers consist of a rectangular grid of neurons. It requires that the previous layer also be a rectangular grid of neurons. Each neuron takes inputs from a rectangular section of the previous layer; the weights for this rectangular section are the same for each neuron in the convolutional layer. Thus, the convolutional layer is just an image convolution of the previous layer, where the weights specify the convolution filter.
Fully-Connected layer 的輸入和輸出的尺寸都是固定的,每一個(gè)神經(jīng)元對(duì)應(yīng)一個(gè)輸出。根據(jù) Andrew NG 的 UFLDL,我產(chǎn)生了這種觀念:卷積層只有一個(gè)神經(jīng)元,這個(gè)神經(jīng)元就是 kernel,是 weight 的矩陣。我突然發(fā)覺這種觀念可能有問題。
我現(xiàn)在的理解是這樣的,不知道有沒有錯(cuò)。一般看到,kernel 只有一個(gè),而 convolution layer 的輸入是沒有大小限制的,而輸出也固定,根據(jù)圖像大小產(chǎn)生不同大小的 feature map。如果換個(gè)角度看,convolution layer 是一個(gè) (N?m+1)×(N?m+1) 個(gè) m×m 的 kernel 的神經(jīng)元,每個(gè)神經(jīng)元對(duì)應(yīng)著自己的感受域,產(chǎn)生一個(gè)輸出:如果這樣定義,convolution layer 也是輸入輸出大小固定的。而 weight-sharing 也很好理解了,就是這 (N?m+1)×(N?m+1) 個(gè) kernel 現(xiàn)在變成了同一個(gè),他們 share weight。而文章提出的方法就是,不再使用整個(gè) feature map 做 weight-sharing,用同一個(gè) kernel,而是分區(qū)域使用不同的 kernel。
輸入?yún)^(qū)域似乎也和我想的不一樣,原文的 input range 是臉部區(qū)域 + 一個(gè)百分比...,我覺得我當(dāng)時(shí)沒看到是不是不太合適....
看完我大概是怎么一個(gè)思路:先修改輸入?yún)^(qū)域;
實(shí)現(xiàn) locally weight-sharing 看看效果;
進(jìn)一步提高再實(shí)現(xiàn) cascaded 結(jié)構(gòu),這是后話。
調(diào)整輸入范圍
根據(jù)上次閱讀論文的想法,先測(cè)試左眼的檢測(cè),進(jìn)行數(shù)據(jù)清洗,只截取左眼。結(jié)果發(fā)現(xiàn),雖然輸出的 cost 變小了,但是看圖片依然是 underfit。
進(jìn)行 64 樣本的測(cè)試,發(fā)現(xiàn)依舊是 underfit,這實(shí)在詭異,難道是 Bug?那么測(cè)試 1 樣本試試,還是不準(zhǔn)。輸出預(yù)測(cè)值和坐標(biāo)試試....咦,數(shù)據(jù)績小,所以幾乎完美重合,那么打印怎么會(huì)有那么巨大的位置錯(cuò)誤,這只能解釋為我的程序哪里寫錯(cuò)了。
理理思路,程序的邏輯大概是:
Created with Rapha?l 2.1.2Create DBLE DataLayerCNNLE Feature Extract
很可能是某個(gè)數(shù)值忘記加減,導(dǎo)致的偏移。檢查輸出值后發(fā)現(xiàn),輸出的訓(xùn)練坐標(biāo)和預(yù)測(cè)坐標(biāo)是幾乎相同的。這就說明:訓(xùn)練數(shù)據(jù)生成錯(cuò)了
訓(xùn)練圖像框錯(cuò)了
測(cè)試后發(fā)現(xiàn),確實(shí)是自己 normalize 監(jiān)督信號(hào)的時(shí)候把監(jiān)督信號(hào)弄錯(cuò)了。在選取 sub-region 時(shí)候并不需要 normalize 坐標(biāo),只有 resize 才需要,大腦故障了。調(diào)整后發(fā)現(xiàn),無論是損失函數(shù),還是肉眼觀察結(jié)果,比起之前大大靠譜,非常好。
總結(jié)
以上是生活随笔為你收集整理的cascade down_Cascaded CNN 方法寻找人脸关键点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 曝佳能在开发全像素四核对焦全画幅相机 解
- 下一篇: 美丽说怎么开店铺想开一家属于自己的网店搞
