SVM write/load problems with kernels other than linear (Bug #4455)


Added by Jens Garstka over 9 years ago. Updated over 9 years ago.


Status:New Start date:2015-07-01
Priority:Normal Due date:
Assignee:Maksim Shabunin % Done:

0%

Category:ml
Target version:3.0
Affected version:branch 'master' (3.0-dev) Operating System:Linux
Difficulty:Easy HW Platform:x64
Pull request:

Description

Within the implementation of the SVMs write and read methods (modules/ml/src/svm.cpp, lines 2022 ff and 2139 ff), the author makes the assumption, that support vector indices are not required in 2-class problems. That is probably correct if a linear kernel is used (i.e., when you have only one support vector). But with other kernels (in my case with an RBF kernel), the support vector indices are definitly required.

I've added a git diff where this questionable conditions are commented out. Without these lines everything works fine.

IMHO the lines should be removed.


svm.patch - git diff where questionable conditions will be commented out (1.5 kB) Jens Garstka, 2015-07-01 10:32 am


History

Updated by Hyunjun Kim over 9 years ago

Hi, I was able to reproduce the error. I confirmed that cv::Algorithm::load() works well only with SVM::LINEAR kernel.

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp" 
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>

using namespace cv;
using namespace cv::ml;

int main(int, char**)
{
    // Data for visual representation
    int width = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // Set up training data
    int labels[4] = {1, -1, -1, -1};
    Mat labelsMat(4, 1, CV_32SC1, labels);

    float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
    Mat trainingDataMat(4, 2, CV_32FC1, trainingData);

    // Set up SVM's parameters
    Ptr<ml::SVM> svm = ml::SVM::create();
    svm->setType(ml::SVM::C_SVC);
    svm->setKernel(SVM::INTER); // Algorithm::load() works well with SVM::LINEAR
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

    // Train the SVM
    svm->train(ml::TrainData::create(trainingDataMat, ml::ROW_SAMPLE, labelsMat));

    // Save and load SVM
    svm->save("ex_svm.xml");
    svm= cv::Algorithm::load<ml::SVM>("ex_svm.xml"); // something is wrong

    Vec3b green(0,255,0), blue (255,0,0);
    // Show the decision regions given by the SVM
    for (int i = 0; i < image.rows; ++i)
        for (int j = 0; j < image.cols; ++j)
        {
            Mat sampleMat = (Mat_<float>(1,2) << j,i);
            float response = svm->predict(sampleMat);

            if (response == 1)
                image.at<Vec3b>(i,j)  = green;
            else if (response == -1)
                image.at<Vec3b>(i,j)  = blue;
        }

    // Show the training data
    int thickness = -1;
    int lineType = 8;
    circle( image, Point(501,  10), 5, Scalar(  0,   0,   0), thickness, lineType );
    circle( image, Point(255,  10), 5, Scalar(255, 255, 255), thickness, lineType );
    circle( image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType );
    circle( image, Point( 10, 501), 5, Scalar(255, 255, 255), thickness, lineType );

    // Show support vectors
    thickness = 2;
    lineType  = 8;

    Mat sv = svm->getSupportVectors();

    for (int i = 0; i < sv.rows; ++i)
    {
        const float* v = sv.ptr<float>(i);
        circle( image,  Point( (int) v[0], (int) v[1]),   6,  Scalar(128, 128, 128), thickness, lineType);
    }

    imwrite("result.png", image);        // save the image

    imshow("SVM Simple Example", image); // show it to the user
    waitKey(0);

}

Updated by Maksim Shabunin over 9 years ago

  • Assignee set to Maksim Shabunin

Updated by Maksim Shabunin over 9 years ago

Issue has been transferred to GitHub: https://github.com/Itseez/opencv/issues/5054

Also available in: Atom PDF