OpenCV神经网络Sigmoid输出 [英] OpenCV Neural Network Sigmoid Output

查看:338
本文介绍了OpenCV神经网络Sigmoid输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用OpenCV一段时间。我决定最近检查它的机器学习的力量。所以我最终实现了一个神经网络的面部识别。总结我的面部识别策略:

I have been using OpenCV for a quite time. I decided to check its power for Machine Learning lately. So I ended up with implementing a neural network for face recognition. To summarize my strategy for face recognition :


  1. 从某个面部数据库的csv读取图片。


  2. 应用PCA进行维数减少。

  3. 使用PCA的投影来训练网络。

  4. 使用训练有素的网络预测测试数据。

  1. Read images from a csv of some face database.
  2. Roll images to a Mat array row wise.
  3. Apply PCA for dimensionality reduction.
  4. Use projections of PCA to train the network.
  5. Predict the test data using the trained network.

因此,在预测阶段之前一切正常。我使用最大响应输出单元来分类面部。所以通常OpenCV的sigmoid实现应该给出在-1到1的范围内的值,这在文档中说明。 1是类的最大闭包。在我得到接近0的精度后,我检查每个类的每个测试数据的输出响应。我被惊讶的价值观: 14.53,-1.7,#IND 。如果应用Sigmoid,我怎么能得到这些值?

So everything was OK until the prediction stage. I was using the max responsed output unit to classify the face. So normally OpenCV's sigmoid implementation should give values in range of -1 to 1 which is stated at the docs. 1 is the max closure to class. After I got nearly 0 accuracy I checked the output responses for each class for each test data. I was suprised with the values : 14.53, -1.7 , #IND . If sigmoid was applied, how could i get these values ? Where am i doing wrong ?

为了帮助你理解这个问题,对于想知道如何应用PCA和使用它与NN我想分享我的代码:

To help you understand the matter and for the ones wondering how to apply PCA and use it with NN I m sharing my code :

阅读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标签 / p>

Converting vector of labels to Mat of labels

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;
}

MAIN

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;
}

注意:我使用AT& T我的数据集的前20个类。

NOTE: I used AT&T 's first 20 class for my dataset.

推荐答案

感谢Canberk Ba​​ci的评论,我设法克服了Sigmoid输出差异。 问题似乎是默认参数mlp的创建函数,它将alpha和beta 0作为默认值。当它们都被给定为1时,Sigmoid函数的工作方式与文档中所述的一样,并且神经网络可以预测某事,但是当然会有错误。

Thanks to Canberk Baci's comment I managed to overcome sigmoid output discrepancy. Problem seems to be at default parameters of mlp 's create function which takes alpha and beta 0 as default. When they both are given as 1, sigmoid function works as it was stated in the docs and neural network can predict something but with errors of course.

神经网络:

通过修改一些参数,如动量等,没有任何光照校正算法,我得到%72精度的数据集(随机抽样936列车,262测试图像)前20个类的CroppedYaleB从opencv教程。对于其他因素提高精度;当我应用PCA时,我直接将减少的维度大小为500.这也可能降低精度,因为保留的方差可能低于%95或更差。因此,当我有空闲时间时,我将应用这些提高准确度:

By modifying some parameters like momentum etc, and without any illumunation correction algorithm, I got %72 accuracy on the dataset of (randomly sampled 936 train, 262 test images ) first 20 classes of CroppedYaleB from opencv tutorials. For the other factors to increase accuracy; when I applied PCA, I directly gave the reduced dimension size as 500. This may also reduce accuracy because retained variance may be below %95 or worse. So when I have free time I will apply these to increase accuracy :


  1. Tan Triggs照明校正


  2. 修改神经网络参数(我希望我们在OpenCV库中拥有更少的参数化NN)

我分享了这些内容,因此有人可能想知道如何提高NN的分类精确度。

I shared these so that someone may wonder how to increase the classification accuracy of NN. I hope it helps.

您可以在这里追踪这个问题:
http://code.opencv.org/issues/3583

By the way you can track the issue about this here: http://code.opencv.org/issues/3583

这篇关于OpenCV神经网络Sigmoid输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆