生活随笔
收集整理的這篇文章主要介紹了
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分類代碼
[cpp] view plain
copy #include?<opencv2/core.hpp> ??#include?<opencv2/imgproc.hpp> ??#include?"opencv2/imgcodecs.hpp" ??#include?<opencv2/highgui.hpp> ??#include?<opencv2/ml.hpp> ???? using ?namespace ?std;??using ?namespace ?cv;??using ?namespace ?cv::ml;???? int ?main(int ,?char **)??{?? ?????? ????int ?width?=?512,?height?=?512;?? ????Mat?image?=?Mat::zeros(height,?width,?CV_8UC3);?? ?? ?????? ?????? ????int ?labels[4]?=?{?1,?-1,?-1,?1?};?? ????float ?trainingData[4][2]?=?{?{?1,?2?},?{?-1,?-10?},?{?1,?-2?},?{?2,?1?}?};?? ?????? ?????? ????Mat?trainingDataMat(4,?2,?CV_32FC1,?trainingData);?? ????Mat?labelsMat(4,?1,?CV_32SC1,?labels);?? ?????? ?? ?? ?????? ?????? ?? ????Ptr<SVM>?svm?=?SVM::create();?? ????svm->setType(SVM::C_SVC);?? ????svm->setKernel(SVM::LINEAR);?? ????svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER,?100,?1e-6));?? ?????? ?????? ????svm->train(trainingDataMat,?ROW_SAMPLE,?labelsMat);?? ?????? ?? ?????? ?????? ????Vec3b?green(0,?255,?0),?blue(255,?0,?0);?? ????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;?? ????????}?? ?????? ?? ?????? ?????? ????int ?thickness?=?-1;?? ????int ?lineType?=?8;?? ????circle(image,?Point(1,?2),?5,?Scalar(0,?0,?0),?thickness,?lineType);?? ????circle(image,?Point(-1,?-10),?5,?Scalar(255,?255,?255),?thickness,?lineType);?? ????circle(image,?Point(1,?-2),?5,?Scalar(255,?255,?255),?thickness,?lineType);?? ????circle(image,?Point(2,?1),?5,?Scalar(255,?255,?255),?thickness,?lineType);?? ?????? ?? ?????? ?????? ????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);?? ????}?? ?????? ?? ????Mat?res;?? ????float ?teatData[1][2]?=?{?{?1,?-11?}?};?? ????Mat?query(1,?2,?CV_32FC1,?teatData);?? ?????? ????svm->predict(query,?res);?? ????cout?<<?res;?? ????imwrite("result.png" ,?image);??????? ?? ????imshow("SVM?Simple?Example" ,?image);????? ????waitKey(0);?? ?? }??
需要說明的是: 在OpenCV中,SVM多分類方式被隱藏參數,在調用函數svm->train() 時,定義函數參數時候,直接輸入多類別樣本以及其標簽即可
總結
以上是生活随笔 為你收集整理的SVM 多分类 -SVM分类opencv3.0源代码 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。