SVM 多分类 -SVM分类opencv3.0源代码

SVM的理论知识见 SVM的一些总结与认识 --入门级 

之前一直以为,用SVM做多分类,不就是用多个SVM分类么,请形状类似于一个二叉树,如下:

即,将所有样本当作输入,其中在训练第一个分类器SVM_1的时候,其正样本为属于类别1的样本,其负样本为剩余的其他所有样本,这就称为 一对其余法,这样做虽然训练的时间从道理上来讲是相对较快的,但是它会带来一系列的问题:

1. 有可能有一个样本在部分分类器 (多于一个,比如2个SVM中,或者更加极端的情况是在所有分类器) 中将其分为正(负)样本,简单的说,就是有不止一个分类器声称它     属于自己,那么便出现错误。相反,如果说,没有一个分类器声称它属于某一个分类器,那么同样出现误分类,

2.一经误分类,则结果误分类。

3.数据集倾斜。这个问题是最影响训练出来的分类器性能的情况,就是说,在训练其中一个训练器的时候,只有某一类作为正样本,其余类别作为负样本,那么导致正      负样本数量出现严重不平衡情况。

其优点明显弱于确定,所以这种情形在实际应用中是不可取的。

第二种方法:一对一

实际应用中,第一种方法得到的模型精度不高,训练时间也同样不占优势。那么这一对一的方法又是怎么回事儿呢?顾名思义:训练多个二分类SVM,也就是任意两个类别训练一个SVM,这样会有一个问题,比如:我有4类样本,按照这种方法多分类的话,需要训练6个SVM,推广到k 个类别则需要k(k-1)/2 个分类器。但他是怎么分类的呢?

简单的说,投票!所有分类器都对这个样本做一个分类(预测),得到的分类结果最多,那么就将这个样本分到这一类。这样做的好处就是,样本怎么样都会有一个预测值,而不会出现无类别的预测结果。目前流行的SVM工具包 LIBSVM--台湾大学.Chih-Chung Chung and Chih-Jen Lin 就是用的这种方法作为SVM多分类的方法。

第三种方法:DAG SVM

其结构形状如下:

这样分类时,我们可以先问分类器 1v5 (意思是它能回答“是第1类还是第5类”) ,如果回答是5,即往左走,再问“是2还是5”,这样一直问下去,这样做的好处其实是,我们在分类的时候,实际上只是调用了4个分类器。耗时更短,同样不会出现分类重叠或不可分类现象。

现在DAG方法根节点的选取(也就是如何选第一个参与分类的分类器),也有一些方法可以改善整体效果,我们总希望根节点少犯错误为好,因此参与第一次分类的两个类别,最好是差别特别特别大,大到以至于不太可能把他们分错;或者我们就总取在两类分类中正确率最高的那个分类器作根节点,或者我们让两类分类器在分类的时候,不光输出类别的标签,还输出一个类似“置信度”的东东,当它对自己的结果不太自信的时候,我们就不光按照它的输出走,把它旁边的那条路也走一走,等等。

---------------------- OpenCV3.0 SVM分类代码 -------------

下面是在OpenCV3.0+Vs2013的平台上(其配置方法见本人另一博文 win7平台下vs2013配置OpenCV3.0 )的SVM分类代码

  1. #include <opencv2/core.hpp>  
  2. #include <opencv2/imgproc.hpp>  
  3. #include "opencv2/imgcodecs.hpp"  
  4. #include <opencv2/highgui.hpp>  
  5. #include <opencv2/ml.hpp>  
  6.   
  7. using namespace std;  
  8. using namespace cv;  
  9. using namespace cv::ml;  
  10.   
  11. int main(intchar**)  
  12. {  
  13.     // Data for visual representation  
  14.     int width = 512, height = 512;  
  15.     Mat image = Mat::zeros(height, width, CV_8UC3);  
  16.   
  17.     // Set up training data  
  18.     //! [setup1]  
  19.     int labels[4] = { 1, -1, -1, 1 };  
  20.     float trainingData[4][2] = { { 1, 2 }, { -1, -10 }, { 1, -2 }, { 2, 1 } };  
  21.     //! [setup1]  
  22.     //! [setup2]  
  23.     Mat trainingDataMat(4, 2, CV_32FC1, trainingData);  
  24.     Mat labelsMat(4, 1, CV_32SC1, labels);  
  25.     //! [setup2]  
  26.   
  27.   
  28.     // Train the SVM  
  29.     //! [init]  
  30.   
  31.     Ptr<SVM> svm = SVM::create();  
  32.     svm->setType(SVM::C_SVC);  
  33.     svm->setKernel(SVM::LINEAR);  
  34.     svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));  
  35.     //! [init]  
  36.     //! [train]  
  37.     svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);  
  38.     //! [train]  
  39.   
  40.     // Show the decision regions given by the SVM  
  41.     //! [show]  
  42.     Vec3b green(0, 255, 0), blue(255, 0, 0);  
  43.     for (int i = 0; i < image.rows; ++i)  
  44.         for (int j = 0; j < image.cols; ++j)  
  45.         {  
  46.         Mat sampleMat = (Mat_<float>(1, 2) << j, i);  
  47.         float response = svm->predict(sampleMat);  
  48.   
  49.         if (response == 1)  
  50.             image.at<Vec3b>(i, j) = green;  
  51.         else if (response == -1)  
  52.             image.at<Vec3b>(i, j) = blue;  
  53.         }  
  54.     //! [show]  
  55.   
  56.     // Show the training data  
  57.     //! [show_data]  
  58.     int thickness = -1;  
  59.     int lineType = 8;  
  60.     circle(image, Point(1, 2), 5, Scalar(0, 0, 0), thickness, lineType);  
  61.     circle(image, Point(-1, -10), 5, Scalar(255, 255, 255), thickness, lineType);  
  62.     circle(image, Point(1, -2), 5, Scalar(255, 255, 255), thickness, lineType);  
  63.     circle(image, Point(2, 1), 5, Scalar(255, 255, 255), thickness, lineType);  
  64.     //! [show_data]  
  65.   
  66.     // Show support vectors  
  67.     //! [show_vectors]  
  68.     thickness = 2;  
  69.     lineType = 8;  
  70.     Mat sv = svm->getSupportVectors();  
  71.   
  72.     for (int i = 0; i < sv.rows; ++i)  
  73.     {  
  74.         const float* v = sv.ptr<float>(i);  
  75.         circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);  
  76.     }  
  77.     //! [show_vectors]  
  78.   
  79.     Mat res;  
  80.     float teatData[1][2] = { { 1, -11 } };  
  81.     Mat query(1, 2, CV_32FC1, teatData);  
  82.       
  83.     svm->predict(query, res);  
  84.     cout << res;  
  85.     imwrite("result.png", image);     // save the image  
  86.   
  87.     imshow("SVM Simple Example", image);   // show it to the user  
  88.     waitKey(0);  
  89.   
  90. }  

需要说明的是:在OpenCV中,SVM多分类方式被隐藏参数,在调用函数svm->train() 时,定义函数参数时候,直接输入多类别样本以及其标签即可


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值