2014-02-24 159 views
3

我一直在使用OpenCV一段時間。我決定最近檢查它的機器學習的力量。所以我最終實現了一個用於人臉識別的神經網絡。總結一下我的人臉識別策略:OpenCV神經網絡Sigmoid輸出

  1. 從某個臉部數據庫的csv中讀取圖像。
  2. 將圖像逐行掃描到Mat陣列。
  3. 應用PCA降維。
  4. 使用PCA預測來訓練網絡。
  5. 使用訓練好的網絡預測測試數據。

    所以一切都很好,直到預測階段。我正在使用最大響應輸出單位對臉部進行分類。所以通常OpenCV的sigmoid實現應該給出-1到1的值,這在文檔中有說明。 1是課堂的最大封閉。在準確度接近0之後,我檢查了每個測試數據的每個類的輸出響應。我驚訝的價值觀:14.53,-1.7,#IND。如果sigmoid被應用,我怎麼能得到這些值?我在哪裏做錯了?

    爲了幫助您瞭解此事,併爲那些不知道如何運用主成分分析,並與NN使用它我米分享我的代碼:

閱讀CSV

 
void read_csv(const string& filename, vector& images, vector& labels, char separator = ';') 
{ 
    std::ifstream file(filename.c_str(), ifstream::in); 
    if (!file) 
    { 
     string error_message = "No valid input file was given, please check the given filename."; 
     CV_Error(1, error_message); 
    } 
    string line, path, classlabel; 
    while (getline(file, line)) 
    { 
     stringstream liness(line); 

     getline(liness, path, separator); 
     getline(liness, classlabel); 

     if(!path.empty() && !classlabel.empty()) 
     { 
      Mat im = imread(path, 0); 

      images.push_back(im); 
      labels.push_back(atoi(classlabel.c_str())); 
     } 
    } 
} 

逐行滾動圖像:

Mat rollVectortoMat(const vector<Mat> &data) 
{ 
    Mat dst(static_cast<int>(data.size()), data[0].rows*data[0].cols, CV_32FC1); 
    for(unsigned int i = 0; i < data.size(); i++) 
    { 
     Mat image_row = data[i].clone().reshape(1,1); 
     Mat row_i = dst.row(i);          
     image_row.convertTo(row_i,CV_32FC1, 1/255.); 
    } 
    return dst; 
} 

轉換標籤的載體,MAT標籤

Mat getLabels(const vector<int> &data,int classes = 20) 
{ 
    Mat labels(data.size(),classes,CV_32FC1); 

    for(int i = 0; i <data.size() ; i++) 
    { 
     int cls = data[i] - 1; 
     labels.at<float>(i,cls) = 1.0; 
    } 

    return labels; 
} 

主要

int main() 
{ 

    PCA pca; 

    vector<Mat> images_train; 
    vector<Mat> images_test; 
    vector<int> labels_train; 
    vector<int> labels_test; 

    read_csv("train1k.txt",images_train,labels_train); 
    read_csv("test1k.txt",images_test,labels_test); 

    Mat rawTrainData = rollVectortoMat(images_train);      
    Mat rawTestData = rollVectortoMat(images_test);     

    Mat trainLabels = getLabels(labels_train); 
    Mat testLabels = getLabels(labels_test); 

    int pca_size = 500; 

    Mat trainData(rawTrainData.rows, pca_size,rawTrainData.type()); 
    Mat testData(rawTestData.rows,pca_size,rawTestData.type()); 


    pca(rawTrainData,Mat(),CV_PCA_DATA_AS_ROW,pca_size); 

    for(int i = 0; i < rawTrainData.rows ; i++) 
     pca.project(rawTrainData.row(i),trainData.row(i)); 

    for(int i = 0; i < rawTestData.rows ; i++) 
     pca.project(rawTestData.row(i),testData.row(i)); 



    Mat layers = Mat(3,1,CV_32SC1); 
    int sz = trainData.cols ; 

    layers.row(0) = Scalar(sz); 
    layers.row(1) = Scalar(1000); 
    layers.row(2) = Scalar(20); 

    CvANN_MLP mlp; 
    CvANN_MLP_TrainParams params; 
    CvTermCriteria criteria; 

    criteria.max_iter = 1000; 
    criteria.epsilon = 0.00001f; 
    criteria.type  = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS; 

    params.train_method = CvANN_MLP_TrainParams::BACKPROP; 
    params.bp_dw_scale  = 0.1f; 
    params.bp_moment_scale = 0.1f; 
    params.term_crit  = criteria; 

    mlp.create(layers,CvANN_MLP::SIGMOID_SYM); 
    int i = mlp.train(trainData,trainLabels,Mat(),Mat(),params); 

    int t = 0, f = 0; 

    for(int i = 0; i < testData.rows ; i++) 
    { 
     Mat response(1,20,CV_32FC1); 
     Mat sample = testData.row(i); 

     mlp.predict(sample,response); 

     float max = -1000000000000.0f; 
     int cls = -1; 

     for(int j = 0 ; j < 20 ; j++) 
     { 
      float value = response.at<float>(0,j); 

      if(value > max) 
      { 
       max = value; 
       cls = j + 1; 
      } 
     } 

     if(cls == labels_test[i]) 
      t++; 
     else 
      f++; 
    } 


    return 0; 
} 

注:我曾經在& T「第一個20級的我的數據集。

+3

可以請你設置的參數通過手,即mlp.create(層,CvANN_MLP :: SIGMOID_SYM,1,1); – baci

+0

如果它工作提交錯誤報告,因爲默認值0對alpha和beta沒有意義。 – baci

+0

它似乎令人驚訝地將S形輸出值修正爲建議的範圍。現在,我正在使用其他參數來提高準確性。我將很快發佈我的神經網絡經驗。謝謝你的方式:) – yutasrobot

回答

4

感謝Canberk Ba​​ci的評論我設法克服了sigmoid輸出差異。 問題似乎是mlp的創建函數的默認參數,它將alpha和beta 0作爲默認值。當它們都是1時,sigmoid函數就像它在文檔中所述的那樣工作,並且神經網絡可以預測某些事情,但是當然會有錯誤。

而對於神經網絡的結果:

通過修改等動量等某些參數,且無任何illumunation校正算法,我%72準確性上的數據集(隨機取樣936列車,262個測試圖像)來自opencv教程的前20類CroppedYaleB。對於其他因素來提高準確性;當我應用PCA時,我直接將縮減的維度大小設爲500.這也可能降低準確性,因爲保留的變化可能低於95%或更差。所以,當我有空閒時間,我會將這些以提高準確性:

  1. 譚Triggs光量校正
  2. 列車PCA與0.95的PCA大小保留95%的方差。
  3. 修改神經網絡參數(我希望我們有一個不太參數NN在OpenCV庫)

我分享這些所謂有人可能會問,如何提高NN的分類精度。我希望它有幫助。

通過您可以跟蹤這個位置問題的方式: http://code.opencv.org/issues/3583