1. 程式人生 > >基於 CNN的年齡和性別檢測

基於 CNN的年齡和性別檢測

自2012年深度學習火起來後,AlexNet,vgg16,vgg19,gooGleNet,caffeNet,faster RCNN等,各種模型層出不群,頗有文藝復興時的形態。

在各種頂會論文中,對年齡和性別的檢測的論文還是比較少的。而本文將要講解的是2015年的一篇cvpr,Age and Gender Classification using Convolutional Neural Networks。官方連結為

理論基礎:

其整體結構如下圖所示,輸入一幅圖片,然後經過3個卷基層,2個全連結層,最後經過svm分類器分類,輸出相應的結果。



詳細結構如下圖所示,其中norm層為了提高模型的泛化能力,drop層是為了防止過擬合。

其中左中右分別為第一二三個卷基層,下面的為第六七八個全連線層。


程式執行:

可以寫一個簡單的shell指令碼來進行執行測試,touch一個.sh檔案,隨便起個名字,輸入如下的指令碼,然後命令列執行就可以輸出結果。其中路徑名換成自己電腦的實際路徑名。

#!/bin/bash
#directed by watersink([email protected])

echo "Begin gender....."

./build/examples/cpp_classification/classification.bin \
  models/cnn_age_gender/deploy_gender.prototxt \
  models/cnn_age_gender/gender_net.caffemodel \
  data/cnn_age_gender/mean.binaryproto \
  data/cnn_age_gender/genderlabels.txt \
  data/cnn_age_gender/example_image.jpg

echo "Begin age....."

./build/examples/cpp_classification/classification.bin \
  models/cnn_age_gender/deploy_age.prototxt \
  models/cnn_age_gender/age_net.caffemodel \
  data/cnn_age_gender/mean.binaryproto \
  data/cnn_age_gender/agelabels.txt \
  data/cnn_age_gender/example_image.jpg
 echo "Done.

classification.bin為caffe自帶的二進位制檔案,用於實現分類。

deploy_gender.prototxt,deploy_age.prototxt分別為性別,年齡部署或者測試時候的模型檔案

gender_net.caffemodel,age_net.caffemodel分別為性別,年齡訓練好的權值檔案

mean.binaryproto,為訓練的樣本的均值檔案,減均值時使用,可以達到更好的檢測效果

genderlabels.txt,agelabels.txt為性別,年齡的標籤檔案,具體內容如下

genderlabels.txt中的內容:
male 1
female 0

agelabels.txt中的內容:

0-2 0
4-6 1
8-13 2
15-20 3
25-32 4
38-43 5
48-53 6
60- 7
example_image.jpg,為隨便一張想要測試的圖片

實驗結果:


性別識別率:

年齡識別率:

訓練自己的模型:

論文的原作者給出了自己的5-folder訓練檔案,首先我們對原作者的訓練資料進行分析。

通過上面的資料可以看出,性別資料反面基本是1:1比例進行的。而年齡方面並沒有執行大概的1:1:1:1:1:1:1:1比例,而是3:3:3:3:6:3:1:1,對於這樣的訓練比例,我個人認為是很不科學和合理的,所謂的mini-batch,應該是每個batch中的屬性和整體的基本是一樣的才可以。簡單的說,任意給一張影象,這張影象中人物屬於哪一個年齡段是都有可能的,也就是是平均概率的。(個人見解,如有錯誤,希望大家指正)

下面通過一個簡單的c++程式來獲得和作者一樣的txt檔案。

int main()
{
	
	vector<string>file_folder;
	file_folder.push_back("fold_0_data.txt");
	file_folder.push_back("fold_1_data.txt");
	file_folder.push_back("fold_2_data.txt");
	file_folder.push_back("fold_3_data.txt");
	file_folder.push_back("fold_4_data.txt");

	ofstream file_stream_gender_out("gender.txt", ios::app);
	ofstream file_stream_age_out("age.txt", ios::app);

	char buffer[500];
	char str1[50], str2[50], str3[50], str4[50], str5[50], str6[50];
	for (int i = 0; i < file_folder.size();i++)
	{
		ifstream file_stream_in(file_folder[i]);
		file_stream_in.getline(buffer, 400);//提取標題


		while (!file_stream_in.eof())
		{
			file_stream_in.getline(buffer,400);
			sscanf(buffer, "%s %s %s %s %s %s", &str1, &str2, &str3, &str4, &str5, &str6);
			
				string tmp1 = str3, tmp2 = str2;
				string address = "F:\\MydataSet\\Adience\\aligned\\landmark_aligned_face." + tmp1 + "." + tmp2;
				Mat image = imread(address);
				if (image.data)
				{
					if (str4[0] == '(')
						file_stream_age_out << "Adience/" << "landmark_aligned_face." << str3 << "." << str2 << " " << str4 << " " << str5 << endl;
					if (strcmp(str6, "f") == 0 || strcmp(str6, "m") == 0 )
						file_stream_gender_out << "Adience/" << "landmark_aligned_face." << str3 << "." << str2 << " " << str6<<endl;
						else
						{
						if(strcmp(str5, "f") == 0 || strcmp(str5, "m") == 0)
						file_stream_gender_out << "Adience/" << "landmark_aligned_face." << str3 << "." << str2 << " " << str5 << endl;
						}

				}

				

		}
		file_stream_in.close();

	}
	file_stream_gender_out.close();
	file_stream_age_out.close();
	return 0;
}

程式執行結束後,將會生成age.txt和gender.txt

有了這2個檔案就可以進行相應的訓練工作了。當然為了得到更好的效果,可以考慮以下3點建議。

(1)對txt中的資料平均分配,不要好多相同的標籤在一起,如果不這樣做的話,需要在輸入層設定shuffle,同樣可以達到相同的效果。

(2)增加一定的樣本,使得年齡的每一個階段數量都大致相同

(3)將影象縮放到256*256,並做aligement

本人處理後資料如下圖所示,大小256*256,做了aligement

cafferoot/examples/imagenet/ (cafferoot為自己的caffe的根目錄)下的create_imagenet.sh

make_imagenet_mean.shtrain_caffenet.sh複製到自己的工程下,分別改名為,create_age.shmake_age_mean.shtrain_age.sh再複製一份,改名為,create_gender.shmake_gender_mean.shtrain_gender.sh並對其中的引數做相應的修改。(如果這一步有疑問,請留言)

年齡的訓練:

執行create_age.sh


執行,make_age_mean.sh


執行,train_age.sh,可以看到得到了68.95%的識別率

性別的訓練:

執行create_gender.sh

執行,make_gender_mean.sh

執行,train_gender.sh,可以看到得到了95.75%的識別率

本人實際在ubuntu14.04+corei7cpu+TitanX上跑的cpu進行年齡或者性別判斷的時間為150ms左右,gpu的時間為2-3ms左右。

在windows7+XeonE3上測試,cpu+debug為120ms左右,cpu+release為30ms左右。

歡迎大家指證與交流……