Ask Your Question
0

svm predict function always return a large number

asked 2015-11-25 10:34:25 -0600

nqthiep gravatar image

updated 2015-11-26 08:49:30 -0600

Hi all,

I trying to implement a simple sample, the purpose is tranning and detect a number. Source as following:

Step 1: Initial data for tranning: I used a collect of images number for traning data,

    Mat vectorMatToMat(vector<Mat> list) {
        if (list.empty()) {
            return Mat();
        }
        int row = list.size();
        int col = list.at(0).rows * list.at(0).cols;
        Mat data(row, col, CV_32FC1);
        int i = 0;
        for (i = 0; i < row; i++) {
            Mat rowMat = list.at(i).reshape(1, 1);
            rowMat.copyTo(data.row(i));
        }
        return data;
    }
    Mat vectorIntToMat(vector<int> list) {
        int row = list.size();
        Mat data(row, 1, CV_32SC1, &list[0]);
        return data;
    }

    Mat dataMat = vectorMatToMat(listImageForTraining);
    Mat dataLabel = vectorIntToMat(listLabel);

Step 2: Init SVM:

Ptr<TrainData> trainData = TrainData::create(dataMat, ROW_SAMPLE, dataLabel);

Ptr<SVM> model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::LINEAR);
model->setC(7);
model->setNu(SVM::NU_SVC);
model->setP(0);
model->setDegree(0);
model->setGamma(20);
model->setCoef0(0);
TermCriteria term(CV_TERMCRIT_ITER +CV_TERMCRIT_EPS, 1000, 1e-6);
model->setTermCriteria(term);
model->train(trainData);

Step 3: trying using SVM for predict:

    int i = 0;
    for (i = 0; i < 15; i++) {
        Mat check = dataMat.row(i);
        ostringstream oss;
        oss << i;
        imshow(oss.str(), check.reshape(1, 128));

        check = check.reshape(1, 1);
        int lable = model->predict(check);

        cout << "Result: " << lable << endl;
    }

Step 4: Result:

Result: -1237234688
Result: 159407376
Result: 159407376
Result: 167908848
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216
Result: 1065353216

As we can see, my result are very large number, although my labels are numbers in 0 to 10. I can not understand why, i think i have a mistake when I init SVM model.

But i dont know how to fix this issue, If there is any idea, please help me.

Thanks & Best Regards,

Thiep

edit retag flag offensive close merge delete

Comments

  1. If you're using C_SVC with a linear kernel, the only parameter to set is C. Though that is not the problem, keeping it simple is always a good idea
  2. After training model, what do you do? Do you save your trained SVM and later load it or what? You have skipped that part. In fact, when you use int lable = svm.predict(check); I see two problems: 1) I don't know where/how the svm variable has been created/initialized and 2) that svm is not a pointer (because you're using . instead of ->), and since you're clearly using OpenCV 3.0, something is wrong there. Please, add the initialization part that is missing
LorenaGdL gravatar imageLorenaGdL ( 2015-11-25 11:57:02 -0600 )edit

I can see that some results are 1065353216. These value could be 1.0f.

Check these posts:

http://stackoverflow.com/questions/24...

http://stackoverflow.com/questions/68...

albertofernandez gravatar imagealbertofernandez ( 2015-11-25 11:59:15 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
3

answered 2015-11-25 23:23:24 -0600

berak gravatar image

updated 2015-11-26 03:17:46 -0600

please replace your vectorIntToMat(listLabel) with a plain Mat(listLabel, true) .

(constructing a Mat with a raw data pointer from a local var is UB)

edit flag offensive delete link more

Comments

@berak: what's the reason for the UB? I've seen that kind of pointer-construction before and I thought it was safe. In fact, now I wonder when and when not it is safe. What's the difference between that and the automatic Mat() conversion?

LorenaGdL gravatar imageLorenaGdL ( 2015-11-26 03:02:33 -0600 )edit
2

@LorenaGdL , this construct is only safe, as long as original data pointer stays in scope. (no data copy is done, no refcounting, just a shallow copy of the pointer)

berak gravatar imageberak ( 2015-11-26 03:09:17 -0600 )edit

@berak: thanks :). I thought data was copied as in other versions of the Mat constructor. It seems 3.0 docs better describe each of such constructors behaviours and parameters

LorenaGdL gravatar imageLorenaGdL ( 2015-11-26 03:19:56 -0600 )edit
1

Thank all your the support. I tried modify as @berak suggest, and my issue solved. @berak: I can't understand. Could you explain for me about the different between your way with my way?

nqthiep gravatar imagenqthiep ( 2015-11-26 10:10:24 -0600 )edit

@nqthiep, Mat data(row, 1, CV_32SC1, &list[0]); copies only the address of the 1st element, not the content of the vector. you also passed a copy of the vector to your function, so once you return from vectorIntToMat, this copy will get deleted, and your labelsMat is invalid, when you want to train the svm

berak gravatar imageberak ( 2015-11-27 00:16:08 -0600 )edit

some reorganizing to have an answer@nqthiep can you accept this one so topic looks solved?

StevenPuttemans gravatar imageStevenPuttemans ( 2015-11-27 05:01:02 -0600 )edit

@berak Thank you so much for your explained. I understood. So, I'd like to solved this ticket.

nqthiep gravatar imagenqthiep ( 2015-11-29 02:51:16 -0600 )edit

@StevenPuttemans: I dont know how to solve this ticket. Please point me.

nqthiep gravatar imagenqthiep ( 2015-11-29 02:53:37 -0600 )edit
1

it's the little hook under the answer, and i'v already done that, ok ?

berak gravatar imageberak ( 2015-11-29 03:03:39 -0600 )edit

Yes, Thank you :)

nqthiep gravatar imagenqthiep ( 2015-12-01 07:37:36 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2015-11-25 10:34:25 -0600

Seen: 1,592 times

Last updated: Nov 26 '15