Ask Your Question
0

How to train my data only once

asked 2013-08-18 08:25:55 -0600

FLY gravatar image

updated 2020-11-11 13:03:21 -0600

This is my code , which i am using for train the dataset but whenever i run the code it again start vectorization and feature counting training etc , and it takes time every time whenever i start , i want it that it should train ones and not takes time again and again

char ch[30];

//--------Using SURF as feature extractor and FlannBased for assigning a new point to the nearest one in the dictionary
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
Ptr<DescriptorExtractor> extractor = new SurfDescriptorExtractor();
SurfFeatureDetector detector(500);
//---dictionary size=number of cluster's centroids
int dictionarySize = 1500;
TermCriteria tc(CV_TERMCRIT_ITER, 10, 0.001);
int retries = 1;
int flags = KMEANS_PP_CENTERS;
BOWKMeansTrainer bowTrainer(dictionarySize, tc, retries, flags);
BOWImgDescriptorExtractor bowDE(extractor, matcher);



void collectclasscentroids() {
    IplImage *img;
    int i,j;
    for(j=1;j<=4;j++)
    for(i=1;i<=60;i++){
        sprintf( ch,"%s%d%s%d%s","train/",j," (",i,").jpg");
                    const char* imageName = ch;
                    img = cvLoadImage(imageName,0);
                    vector<KeyPoint> keypoint;
                    detector.detect(img, keypoint);
                    Mat features;
                    extractor->compute(img, keypoint, features);
                    bowTrainer.add(features);
    }
return;
}
 int _tmain(int argc, _TCHAR* argv[])
    {

    int i,j;
    IplImage *img2;
    cout<<"Vector quantization..."<<endl;
    collectclasscentroids();
    vector<Mat> descriptors = bowTrainer.getDescriptors();
    int count=0;
    for(vector<Mat>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)
    {
       count += iter->rows;
    }
    cout<<"Clustering "<<count<<" features"<<endl;
    //choosing cluster's centroids as dictionary's words
    Mat dictionary = bowTrainer.cluster();
    bowDE.setVocabulary(dictionary);
    cout<<"extracting histograms in the form of BOW for each image "<<endl;
    Mat labels(0, 1, CV_32FC1);
    Mat trainingData(0, dictionarySize, CV_32FC1);
    int k = 0;
    vector<KeyPoint> keypoint1;
    Mat bowDescriptor1;
    //extracting histogram in the form of bow for each image 
   for(j = 1; j <= 4; j++)
    for(i = 1; i <= 60; i++)
            {
              sprintf( ch,"%s%d%s%d%s","train/",j," (",i,").jpg");
              const char* imageName = ch;
              img2 = cvLoadImage(imageName, 0); 
              detector.detect(img2, keypoint1);
              bowDE.compute(img2, keypoint1, bowDescriptor1);
              trainingData.push_back(bowDescriptor1);
              labels.push_back((float) j);
             }
    //Setting up SVM parameters
    CvSVMParams params;
    params.kernel_type = CvSVM::RBF;
    params.svm_type = CvSVM::C_SVC;
    params.gamma = 0.50625000000000009;
    params.C = 312.50000000000000;
    params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 0.000001);
    CvSVM svm;



    printf("%s\n", "Training SVM classifier");

    bool res = svm.train(trainingData, labels, cv::Mat(), cv::Mat(), params);

    cout<<"Processing evaluation data..."<<endl;


    Mat groundTruth(0, 1, CV_32FC1);
    Mat evalData(0, dictionarySize, CV_32FC1);
    k = 0;
    vector<KeyPoint> keypoint2;
    Mat bowDescriptor2;


    Mat results(0, 1, CV_32FC1);;
    for(j = 1; j <= 4; j++)
      for(i = 1; i <= 60; i++)
         {
           sprintf( ch, "%s%d%s%d%s", "eval/", j, " (",i,").jpg");
           const char* imageName = ch;
           img2 = cvLoadImage(imageName,0);
           detector.detect(img2, keypoint2);
           bowDE.compute(img2, keypoint2, bowDescriptor2);
           evalData.push_back(bowDescriptor2);
           groundTruth.push_back((float) j);
           float response = svm.predict(bowDescriptor2);
           results.push_back(response);
         }



    //calculate the number of unmatched classes 
    double errorRate = (double) countNonZero(groundTruth- results) / evalData.rows;

I just learn about the method to save the file of trained data like train.xml and than use it in prediction , but i am not clear about it and its use , Demo code will prefer ... (more)

edit retag flag offensive close merge delete

Comments

My data's dimension is 262144 by 3. I use 78642 train data and 78642 labels. I done training and prediction. I am not sure about, it is right or wrong. I want to display decision region. As per this code ,variable response is used for decision region. So how can i display it?

sumit patel gravatar imagesumit patel ( 2016-03-08 05:58:39 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
3

answered 2013-08-18 22:14:05 -0600

updated 2013-08-19 17:37:20 -0600

To save a SVM use the save function:

svm.save( "my_svm.yml" ); // to save in YML
svm.save( "my_svm.xml" ); // to save in XML
svm.load( "my_svm.yml" ); // to load a trained svm from YML.
svm.load( "my_svm.xml" ); // to load a trained svm from XML.

These functions are inherited from CvStatModel, see the doc here.

Train your SVM once, and save the results. After if you want to evaluate the SVM on other files, use the loading capability.

You could also save and load everything using the OpenCV FileStorage facilities. See samples and doc here. Therefore, you could save your features to test different SVM training, or store features of validation features to test different prediction threshold, etc.

[EDIT]

Simple trick for the SVM. For Bag of Words, the problem is there is no function to store it. You could store the vocabulary and used the BOWImgDescriptorExtractor setVocabulary function (as you did but with the loaded dictionary).

int main( int argc, char** argv )
{
    svm.load( "my_svm.yml" );
    if( !svm.get_support_vector_count() > 0 ) // model not loaded
    {
        [...]
        // Load a vocabulary.
        FileStorage fs( "vocabulary.yml", FileStorage::READ );
        if( fs.isOpened() )
        {
            fs[ "vocabulary" ] >> dictionary;
        }
        else
        {
            fs.Release();
            // Compute your vocabulary.
            [...]
            fs.open( "vocabulary.yml", FileStorage::WRITE );
            fs << "vocabulary" << dictionary;
        }
        fs.Release();
        // do your training here until
        printf("%s\n", "Training SVM classifier");
        bool res = svm.train(trainingData, labels, cv::Mat(), cv::Mat(), params);
        cout<<"Processing evaluation data..."<<endl;
        svm.save( "my_svm.yml" ); // Save your SVM!
    }
    // continue with your test here
}

You probably should cut your program in functions, each one for each step, and store the results in each function (or reload them if they exist).

edit flag offensive delete link more

Comments

Hi Mathieu , I had the same issue as Fly and tried to do as you described below , but I had an error when I tried to predict with my loading svm ( in test stage) ,

OpenCV Error: Bad argument (The sample is not a valid vector) in cvPreparePredictData, file /build/buildd/opencv-2.4.8+dfsg1/modules/ml/src/inner_functions.cpp, line 1099 terminate called after throwing an instance of 'cv::Exception' what(): /build/buildd/opencv-2.4.8+dfsg1/modules/ml/src/inner_functions.cpp:1099: error: (-5) The sample is not a valid vector in function cvPreparePredictData

Balam gravatar imageBalam ( 2015-04-19 17:34:10 -0600 )edit

Hi all, I had the same issue as Mathieu and tried alot. if anyone got the solution please help. thanks.

shakkeebm gravatar imageshakkeebm ( 2016-03-04 08:25:23 -0600 )edit
0

answered 2016-03-04 08:23:26 -0600

Hi all, I had the same issue as Mathieu and tried alot. if anyone got the solution please help. thanks.

edit flag offensive delete link more

Question Tools

Stats

Asked: 2013-08-18 08:25:55 -0600

Seen: 4,047 times

Last updated: Aug 21 '13