Predicting MLP with single sample

asked 2016-10-26 12:17:24 -0600

Angulu gravatar image

updated 2016-10-26 12:20:11 -0600

I have trained MLP as shown in the code below to classify images into 4 classes. My class labels are 1,2,3,4.This trains the model successfully but it thorws an Exception vector out of range during prediction

void train::trainANN(Mat hists, vector<int> labels)
{
    int cols = hists.cols;//size of input layer must be equal to this number of cols
    int rows = hists.rows;//used to determine rows in Mat of responses
    Mat_<float> responses = Mat(labels).reshape(0, rows);

    Ptr<TrainData> trainData = TrainData::create(hists, ROW_SAMPLE, responses);
    Ptr<ANN_MLP> ann = ml::ANN_MLP::create();
    vector<int> layers = { cols, 500, 1 };
    ann->setLayerSizes(layers);
    ann->setActivationFunction(ml::ANN_MLP::ActivationFunctions::SIGMOID_SYM, 1.0, 1.0);
    ann->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP);
    ann->setBackpropMomentumScale(0.1); 
    ann->setBackpropWeightScale(0.1); 
    ann->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10000, 0.00001));
    ann->train(trainData);
}

This is how I predict the model

float train::predictANN(Mat hist)//hist is a row matrix(one sample)
{
    Mat results(1, 4, CV_32FC1);
    float pred = ann->predict(hist, results);//This is the line that throws vector out of range exception
    return pred;
}

I have tried to debug this code but have not fixed the error. Kindly help with why the prediction throws vector out of range exception. Thank you. NB:Am using different number of images per class during training. class 1 = 300 images, class 2 = 340 images etc

edit retag flag offensive close merge delete

Comments

in the prediction, please do not pre-allocate the result Mat, but leave it empty.

(it will have as many rows, as your prediction input has, and as many cols, as the final layer in your net(1 here))

the main problem atm. is - that to predict one of 4 classes, you need to have 4 output nodes, not 1,

also, you would need a different way of setting up your train labels, like here

berak gravatar imageberak ( 2016-10-27 02:01:56 -0600 )edit
1

Thank you for the insight. So shoul I prepare my responses to look like:- 1 0 0 01 0 0 00 1 0 01 0 0 0 Where 1 means sample belong to that respective class (classes columns rows number of training samples)

Angulu gravatar imageAngulu ( 2016-10-27 03:29:08 -0600 )edit

yes, exactly.

berak gravatar imageberak ( 2016-10-27 05:29:31 -0600 )edit

I have created my responses using the code below and predicted with an empty results Matrix but still throwing exception vector subscript out of range

int classes = remove_dups(labels).size();
    Mat responses = Mat::zeros(rows, classes, CV_32F);
    Mat labs = Mat(labels).reshape(0, rows);
    //prepare responses where number of images is not same in all classes
    for (int i = 0; i < hists.rows; i++)
    {
        int x = labs.at<int>(i);
        responses.at<float>(i, (x-1)) = 1.f;
    }
Angulu gravatar imageAngulu ( 2016-10-27 07:12:23 -0600 )edit

I did responses.at<float>(i, (x-1)) = 1.f because my class labels are 1, 2, 3,4 and matrix indexing start at 0. So class 1 labels are found in column with index 0 and class 4 labels in column with index 3 I have also update the train function now my outer layer has 4 nodes

Angulu gravatar imageAngulu ( 2016-10-27 07:22:28 -0600 )edit

"vector subscript out of range" <-- that comes from a std::vector, not a cv::Mat (and imho, your responses are ok.)

atm, i'm guessing, some operation on your labels goes fishy.

try to comment out code from bottom up (starting with the prediction) , and try to localize the error.

berak gravatar imageberak ( 2016-10-27 07:43:53 -0600 )edit

Thank you berak. I just realized I had a mistake in my code. All along I was loading a wrong model file before prediction. I have corrected this now no exception.

Angulu gravatar imageAngulu ( 2016-10-27 07:46:33 -0600 )edit

oook, nice to hear. ;)

berak gravatar imageberak ( 2016-10-27 07:49:54 -0600 )edit

Thank you. Now am doing my prediction as shown in function in question above at the line:- float pred = ann->predict(hist, results). This gives me predicted labels between 0 and 3. But my class labels are 1, 2, 3, 4. my question is, can I add 1 to predicted labels before I check my cumulative scores? Thank you

Angulu gravatar imageAngulu ( 2016-10-27 07:55:48 -0600 )edit

yes, i'd say so.

in the very same way, you subtracted 1 for the training (to make it 0-based) you later add 1 to the prediction (to make it 1-based again)

berak gravatar imageberak ( 2016-10-27 08:02:08 -0600 )edit