人脸验证 DeepID 算法实践
人臉驗(yàn)證 DeepID 算法實(shí)踐
4,610 次閱讀 -?文章作者:雨石? 出處:雨石的博客
目前人臉驗(yàn)證算法可以說是DeepID最強(qiáng),本文使用theano對(duì)DeepID進(jìn)行實(shí)現(xiàn)。關(guān)于deepid的介紹,可以參見我這一片博文?DeepID之三代。
當(dāng)然DeepID最強(qiáng)指的是DeepID和聯(lián)合貝葉斯兩個(gè)算法,本文中只實(shí)現(xiàn)了DeepID神經(jīng)網(wǎng)絡(luò),并用它作為特征提取器來應(yīng)用在其他任務(wù)上。
本文所用到的代碼工程在github上:DeepID_FaceClassify,如果這篇博客幫到了你,求star??瓤?#xff0c;為了github工程的star數(shù)我覺得我太無恥了,哈哈。
實(shí)踐流程
?環(huán)境配置
本工程使用theano庫,所以在實(shí)驗(yàn)之前,theano環(huán)境是必須要配的,theano環(huán)境配置可以參見theano document。文檔已經(jīng)較為全面,本文不再贅述,在下文中,均假設(shè)讀者已經(jīng)裝好了theano。
代碼概覽
本文所用到的代碼結(jié)構(gòu)如下:
| 1234567891011 | src/├── conv_net│?? ├── deepid_class.py│?? ├── deepid_generate.py│?? ├── layers.py│?? ├── load_data.py│?? └── sample_optimization.py└── data_prepare????├── vectorize_img.py????├── youtube_data_split.py????└── youtube_img_crop.py |
正如文件名命名所指出的,代碼共分為兩個(gè)模塊,即數(shù)據(jù)準(zhǔn)備模塊(data_prepare)和卷積神經(jīng)網(wǎng)絡(luò)模塊(conv_net)。
數(shù)據(jù)準(zhǔn)備
我覺得DeepID的強(qiáng)大得益于兩個(gè)因素,卷積神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)和數(shù)據(jù),數(shù)據(jù)對(duì)于DeepID或者說對(duì)任何的卷積神經(jīng)網(wǎng)絡(luò)都非常重要。
可惜的是,我去找過論文作者要過數(shù)據(jù),可是被婉拒。所以在本文的實(shí)驗(yàn)中,我使用的數(shù)據(jù)并非論文中的數(shù)據(jù)。經(jīng)過下面的描述你可以知道,如果你還有其他的數(shù)據(jù),可以很輕松的用python將其處理為本文DeepID網(wǎng)絡(luò)的輸入數(shù)據(jù)。
以youtube face數(shù)據(jù)為例。它的文件夾結(jié)構(gòu)如下所示,包含三級(jí)結(jié)構(gòu),第一是以人為單位,然后每個(gè)人有不同的視頻,每個(gè)視頻中采集出多張人臉圖像。
| 1 2 3 4 5 6 7 8 | youtube_data/ ├──people_folderA │??├──video_folderA │??│??├──img1.jpg │??│??├──img2.jpg │??│??└──imgN.jpg │??└──video_folderB └──people_folderB |
拿到y(tǒng)outube face數(shù)據(jù)以后,需要做如下兩件事:
- 對(duì)圖像進(jìn)行預(yù)處理,原來的youtube face圖像中,人臉只占中間很小的一部分,我們對(duì)其進(jìn)行裁剪,使人臉的比例變大。同時(shí),將圖像縮放為(47,55)大小。
- 將數(shù)據(jù)集合劃分為訓(xùn)練集和驗(yàn)證集。本文中劃分訓(xùn)練集和驗(yàn)證集的方式如下:
- 對(duì)于每一個(gè)人,將其不同視頻下的圖像混合在一起
- 隨機(jī)化
- 選擇前5張作為驗(yàn)證集,第6-25張作為訓(xùn)練集。
經(jīng)過劃分后,得到7975張驗(yàn)證集和31900訓(xùn)練集。顯然,根據(jù)這兩個(gè)數(shù)字你可以算出一共有1595個(gè)類(人)。
數(shù)據(jù)準(zhǔn)備的代碼使用
注意:?數(shù)據(jù)準(zhǔn)備模塊中以youtube為前綴的的程序是專門用來處理youtube數(shù)據(jù),因?yàn)槠渌麛?shù)據(jù)可能圖像屬性和文件夾的結(jié)構(gòu)不一樣。如果你使用了其他數(shù)據(jù),請(qǐng)閱讀youtube_img_crop.py和youtube_data_split.py代碼,然后重新寫出適合自己數(shù)據(jù)的代碼。數(shù)據(jù)預(yù)處理代碼都很簡單,相信在我代碼的基礎(chǔ)上,不需要改太多,就能適應(yīng)另一種數(shù)據(jù)了。
youtube_img_crop.py
被用來裁剪圖片,youtube face數(shù)據(jù)中圖像上人臉的比例都相當(dāng)小,本程序用于將圖像的邊緣裁減掉,然后將圖像縮放為47×55(DeepID的輸入圖像大小)。
| 12 | Usage: python youtube_img_crop.py aligned_db_folder new_folder |
- aligned_db_folder: 原始文件夾
- new_folder: 結(jié)果文件夾,與原始文件夾的文件夾結(jié)構(gòu)一樣,只不過圖像是被處理后的圖像。
youtube_data_split.py
用來切分?jǐn)?shù)據(jù),將數(shù)據(jù)分為訓(xùn)練集和驗(yàn)證集。
| 1 2 | Usage:pythonyoutube_data_split.pysrc_foldertest_set_filetrain_set_file |
- src_folder: 原始文件夾,此處應(yīng)該為上一步得到的新文件夾
- test_set_file: 驗(yàn)證集圖片路徑集合文件
- train_set_file: 訓(xùn)練集圖片路徑集合文件
test_set_file和train_set_file的格式如下,每一行分為兩部分,第一部分是圖像路徑,第二部分是圖像的類別標(biāo)記。
| 1234 | youtube_47_55/Alan_Ball/2/aligned_detect_2.405.jpg,0youtube_47_55/Alan_Ball/2/aligned_detect_2.844.jpg,0youtube_47_55/Xiang_Liu/5/aligned_detect_5.1352.jpg,1youtube_47_55/Xiang_Liu/1/aligned_detect_1.482.jpg,1 |
vectorize_img.py
用來將圖像向量化,每張圖像都是47×55的,所以每張圖片變成一個(gè)47×55×3的向量。
為了避免超大文件的出現(xiàn),本程序自動(dòng)將數(shù)據(jù)切分為小文件,每個(gè)小文件中只有1000張圖片,即1000×(47×55×3)的矩陣。當(dāng)然,最后一個(gè)小文件不一定是1000張。
| 1 2 | Usage:pythonvectorize_img.pytest_set_filetrain_set_filetest_vector_foldertrain_vector_folder |
- test_set_file:?*_data_split.py生成的
- train_set_file:?*_ata_split.py生成的
- test_vector_folder: 存儲(chǔ)驗(yàn)證集向量文件的文件夾名稱
- train_vector_folder: 存儲(chǔ)訓(xùn)練集向量文件的文件夾名稱
Conv_Net
走完了漫漫前路,終于可以直搗黃龍了。現(xiàn)在是DeepID時(shí)間。吼吼哈嘿。
在conv_net模塊中,有五個(gè)程序文件
- layers.py: 卷積神經(jīng)網(wǎng)絡(luò)相關(guān)的各種層次的定義,包括邏輯斯底回歸層、隱含層、卷積層、max_pooling層等
- load_data.py: 為DeepID載入數(shù)據(jù)。
- sample_optimization.py: 針對(duì)各種層次的一些測(cè)試實(shí)驗(yàn)。
- deepid_class.py: DeepID主程序
- deepid_generate.py: 根據(jù)DeepID訓(xùn)練好的參數(shù),來將隱含層抽取出來
Conv_Net代碼使用
?deepid_class.py
| 12 | Usage: python deepid_class.py vec_valid vec_train params_file |
- vec_valid:?vectorize_img.py生成的
- vec_train:?vectorize_img.py生成的
- params_file: 用來存儲(chǔ)訓(xùn)練時(shí)每次迭代的參數(shù),可以被用來斷點(diǎn)續(xù)跑,由于CNN程序一般需要較長時(shí)間,萬一遇到停電啥的,就可以用得上了。自然,更大的用途是保存參數(shù)后用來抽取特征。
注意:
DeepID訓(xùn)練過程有太多的參數(shù)需要調(diào)整,為了程序使用簡便,我并沒有把這些參數(shù)都使用命令行傳參。如果你想要改變迭代次數(shù)、學(xué)習(xí)速率、批大小等參數(shù),請(qǐng)?jiān)诔绦虻淖詈笠恍姓{(diào)用函數(shù)里改。
deepid_generate.py
可以使用下面的命令來抽取DeepID的隱含層,即160-d的那一層。
| 1 2 | Usage:pythondeepid_generate.pydataset_folderparams_fileresult_folder |
- dataset_folder: 可以是訓(xùn)練集向量文件夾或者驗(yàn)證集向量文件夾。
- params_file:?deepid_class.py訓(xùn)練得到
- result_folder: 結(jié)果文件夾,其下的文件與dataset_folder中文件的文件名一一對(duì)應(yīng),但是結(jié)果文件夾中的向量的長度變?yōu)?60而不是原來的7755。
效果展示
?DeepID 效果
跑完deepid_class.py以后,你可以得到輸出如下。輸出可以分為兩部分,第一部分是每次迭代以及每個(gè)小batch的訓(xùn)練集誤差,驗(yàn)證集誤差等。第二部分是一個(gè)匯總,將epoch train error valid error. 按照統(tǒng)一格式打印了出來。
| 123456789101112131415161718192021222324252627282930 | epoch 15, train_score 0.000444, valid_score 0.066000????????epoch 16, minibatch_index 62/63, error 0.000000epoch 16, train_score 0.000413, valid_score 0.065733????????epoch 17, minibatch_index 62/63, error 0.000000epoch 17, train_score 0.000508, valid_score 0.065333????????epoch 18, minibatch_index 62/63, error 0.000000epoch 18, train_score 0.000413, valid_score 0.070267????????epoch 19, minibatch_index 62/63, error 0.000000epoch 19, train_score 0.000413, valid_score 0.0645330 0.974349206349 0.9629333333331 0.890095238095 0.8974666666672 0.70126984127 0.6666666666673 0.392031746032 0.5201333333334 0.187619047619 0.3606666666675 0.20526984127 0.226 0.054380952381 0.1710666666677 0.0154920634921 0.1288 0.00650793650794 0.1001333333339 0.00377777777778 0.090933333333310 0.00292063492063 0.08611 0.0015873015873 0.079212 0.00133333333333 0.075466666666713 0.00111111111111 0.071466666666714 0.000761904761905 0.06815 0.000444444444444 0.06616 0.000412698412698 0.065733333333317 0.000507936507937 0.065333333333318 0.000412698412698 0.070266666666719 0.000412698412698 0.0645333333333 |
上述數(shù)據(jù)畫成折線圖如下:
向量抽取效果展示
運(yùn)行deepid_generate.py之后, 可以得到輸出如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | loadingdataofvec_test/0.pkl ????buildingthemodel... ????generating... ????writingdatatodeepid_test/0.pkl loadingdataofvec_test/3.pkl ????buildingthemodel... ????generating... ????writingdatatodeepid_test/3.pkl loadingdataofvec_test/1.pkl ????buildingthemodel... ????generating... ????writingdatatodeepid_test/1.pkl loadingdataofvec_test/7.pkl ????buildingthemodel... ????generating... ????writingdatatodeepid_test/7.pkl |
程序會(huì)對(duì)向量化文件夾內(nèi)的每一個(gè)文件進(jìn)行抽取操作,得到對(duì)應(yīng)的160-d向量化文件。
將隱含層抽取出來后,我們可以在一些其他領(lǐng)域上驗(yàn)證該特征的有效性,比如圖像檢索??梢允褂梦业牧硪粋€(gè)github工程進(jìn)行測(cè)試,這是鏈接.使用驗(yàn)證集做查詢集,訓(xùn)練集做被查詢集,來看一下檢索效果如何。
為了做對(duì)比,本文在youtube face數(shù)據(jù)上做了兩個(gè)人臉檢索實(shí)驗(yàn)。
- PCA exp. 在?vectorized_img.py生成的數(shù)據(jù)上,使用PCA將特征降到160-d,然后進(jìn)行人臉檢索實(shí)驗(yàn)。
- DeepID exp. 在?deepid_generate.py生成的160-d數(shù)據(jù)上直接進(jìn)行人臉檢索實(shí)驗(yàn)。
注意:?在兩個(gè)實(shí)驗(yàn)中,我都使用cosine相似度計(jì)算距離,之前做過很多實(shí)驗(yàn),cosine距離比歐式距離要好。
人臉檢索結(jié)果如下:
- 正確率如下:
| PCA | 95.20% | 96.75% | 97.22% |
| DeepID | 97.27% | 97.93% | 98.25% |
- 平均正確率如下:
| PCA | 95.20% | 84.19% | 70.66% |
| DeepID | 97.27% | 89.22% | 76.64% |
Precision意味著在top-N結(jié)果中只要出現(xiàn)相同類別的人,就算這次查詢成功,否則失敗。而AP則意味著,在top-N結(jié)果中需要統(tǒng)計(jì)與查詢圖片相同類別的圖片有多少張,然后除以N,是這次查詢的準(zhǔn)確率,然后再求平均。
從結(jié)果中可以看到,在相同維度下,DeepID在信息的表達(dá)上還是要強(qiáng)于PCA的。
參考文獻(xiàn)
[1]. Sun Y, Wang X, Tang X. Deep learning face representation from predicting 10,000 classes[C]//Computer Vision and Pattern Recognition (CVPR), 2014 IEEE Conference on. IEEE, 2014: 1891-1898.
總結(jié)
以上是生活随笔為你收集整理的人脸验证 DeepID 算法实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Caffe实践】基于Caffe的人脸检
- 下一篇: 选择性模糊及其算法的实现。