rfho_bdss
rfho_bdss

Reputation: 170

c++ confusion matrix error

I'm trying to build a confusion matrix from a set of SVM prediction based on the OpenCV SVM train and predict function as so:

void testClassifier(CvSVM & SVM, 
    std::vector<std::vector<float>> & test_samples,
    std::vector<float> & test_labels,
    const CvSVMParams & params,
    double & tempAcc)
{
    cv::Mat matSamp;
    int response;
    int cnt = 0;
    //std::vector<int> labels = { 0, 1, 2, 3, 4, 5, 6 };
    std::vector<int> exCount = { 0, 0, 0, 0, 0, 0, 0 };
    std::vector<std::vector<double>> confMat = { { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } };


    //test classifier
    for (unsigned int t = 0; t < test_samples.size(); t++)
    {
        matSamp = cv::Mat(test_samples[t].size(), 1, CV_32FC1, test_samples[t].data());
        response = SVM.predict(matSamp);

        if (response == test_labels[t])
        {
            cnt++;
        }

        exCount[test_labels[t]] += 1;
        //cout << test_labels[t] << " " << exCount[test_labels[t]] << endl;
        confMat[test_labels[t]][response] += 1.0;
        //cout << confMat[test_labels[t]][response] << endl;
    }

    cout << "Parameters used: " << endl;
    tempAcc = (double)cnt * 100 / test_samples.size();
    cout << "  C:               " << params.C << endl;
    cout << "  Gamma:           " << params.gamma << endl;
    cout << "you hit " << tempAcc << "% accuracy" << endl << endl;
    cout << confMat[0][0] / exCount[0] * 100 << " " << confMat[0][1] / exCount[1] * 100 << " " << confMat[0][2] / exCount[2] * 100 << " " << confMat[0][3] / exCount[3] * 100 << " " << confMat[0][4] / exCount[4] * 100 << " " << confMat[0][5] / exCount[5] * 100 << " " << confMat[0][6] / exCount[6] * 100 << endl;
    cout << confMat[1][0] / exCount[0] * 100 << " " << confMat[1][1] / exCount[1] * 100 << " " << confMat[1][2] / exCount[2] * 100 << " " << confMat[1][3] / exCount[3] * 100 << " " << confMat[1][4] / exCount[4] * 100 << " " << confMat[1][5] / exCount[5] * 100 << " " << confMat[1][6] / exCount[6] * 100 << endl;
    cout << confMat[2][0] / exCount[0] * 100 << " " << confMat[2][1] / exCount[1] * 100 << " " << confMat[2][2] / exCount[2] * 100 << " " << confMat[2][3] / exCount[3] * 100 << " " << confMat[2][4] / exCount[4] * 100 << " " << confMat[2][5] / exCount[5] * 100 << " " << confMat[2][6] / exCount[6] * 100 << endl;
    cout << confMat[3][0] / exCount[0] * 100 << " " << confMat[3][1] / exCount[1] * 100 << " " << confMat[3][2] / exCount[2] * 100 << " " << confMat[3][3] / exCount[3] * 100 << " " << confMat[3][4] / exCount[4] * 100 << " " << confMat[3][5] / exCount[5] * 100 << " " << confMat[3][6] / exCount[6] * 100 << endl;
    cout << confMat[4][0] / exCount[0] * 100 << " " << confMat[4][1] / exCount[1] * 100 << " " << confMat[4][2] / exCount[2] * 100 << " " << confMat[4][3] / exCount[3] * 100 << " " << confMat[4][4] / exCount[4] * 100 << " " << confMat[4][5] / exCount[5] * 100 << " " << confMat[4][6] / exCount[6] * 100 << endl;
    cout << confMat[5][0] / exCount[0] * 100 << " " << confMat[5][1] / exCount[1] * 100 << " " << confMat[5][2] / exCount[2] * 100 << " " << confMat[5][3] / exCount[3] * 100 << " " << confMat[5][4] / exCount[4] * 100 << " " << confMat[5][5] / exCount[5] * 100 << " " << confMat[5][6] / exCount[6] * 100 << endl;
    cout << confMat[6][0] / exCount[0] * 100 << " " << confMat[6][1] / exCount[1] * 100 << " " << confMat[6][2] / exCount[2] * 100 << " " << confMat[6][3] / exCount[3] * 100 << " " << confMat[6][4] / exCount[4] * 100 << " " << confMat[6][5] / exCount[5] * 100 << " " << confMat[6][6] / exCount[6] * 100 << endl;
    cout << "enter for next matrix" << endl;/**/
    cin.get();
}

but when the matrix entries are outputted some rows sum to greater than 100% and some less. I'm sure its something simple but I've been staring at it for ages with no clue. any ideas?


UPDATE

Im not sure why but the multiple cout I was using affected the return value.

The problem was solved by including the debugging cout in a for loop like this:

for (unsigned int m = 0; m < 7; m++)
{
    for (unsigned int n = 0; n < 7; n++)
    {
        confMat[m][n] = confMat[m][n] * 100 / exCount[m];
        cout << confMat[m][n] << " ";
    }
    cout << endl;
}

Anyone does know why?

Upvotes: 2

Views: 2181

Answers (2)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122830

Seems like I was right with my first guess. In the original you normalize like this:

confMat[i][m] / exCount[m] * 100

while in the correct code you normalize like this:

confMat[m][i] / exCount[m] * 100

Depending on whether exCount is counting the totals per row or per column you only get the correct answer with one of the above lines.

Upvotes: 3

rfho_bdss
rfho_bdss

Reputation: 170

Im not sure why but the multiple cout i was using affected the return value.

by including the debugging couts in a for loop like this:

for (unsigned int m = 0; m < 7; m++)
{
    for (unsigned int n = 0; n < 7; n++)
    {
        confMat[m][n] = confMat[m][n] * 100 / exCount[m];
        cout << confMat[m][n] << " ";
    }
    cout << endl;
}

sorted the issue. any know why?

Upvotes: 1

Related Questions