支持向量機(SVM),起初由vapnik提出時,是作為尋求最優(yōu)(在一定程度上)二分類器的一種技術(shù)。後來它又被拓展到回歸和聚類應(yīng)用。SVM是一種基于核函數(shù)的方法,它通過某些核函數(shù)把特征向量映射到高維空間,然後建立一個線性判別函數(shù)(或者說是一個高維空間中的能夠區(qū)分訓(xùn)練數(shù)據(jù)的最優(yōu)超平面,參考異或那個經(jīng)典例子)。假如SVM沒有明確定義核函數(shù),高維空間中任意兩點距離就需要定義。
解是最優(yōu)的在某種意義上是兩類中距離分割面最近的特征向量和分割面的距離最大化。離分割面最近的特征向量被稱為”支撐向量”,意即其它向量不影響分割面(決策函數(shù))。
有很多關(guān)于SVM的參考文獻,這是兩篇較好的入門文獻。
【Burges98】 C. Burges. "A tutorial on support vector machines for pattern recognition", Knowledge Discovery and Data Mining 2(2), 1998. (available online at [1]).
LIBSVM - A Library for Support Vector Machines. By Chih-Chung Chang and Chih-Jen Lin ([2])
支撐矢量機
class CvSVM : public CvStatModel //繼承自基類CvStatModel{public:// SVM typeenum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 };//SVC是SVM分類器,SVR是SVM回歸// SVM kernel typeenum { LINEAR=0, POLY=1, RBF=2, SIGMOID=3 }; //提供四種核函數(shù),分別是線性,多項式,徑向基,sigmoid型函數(shù)。CvSVM();virtual ~CvSVM();CvSVM( const CvMat* _train_data, const CvMat* _responses,const CvMat* _var_idx=0, const CvMat* _sample_idx=0,CvSVMParams _params=CvSVMParams() );virtual bool train( const CvMat* _train_data, const CvMat* _responses,const CvMat* _var_idx=0, const CvMat* _sample_idx=0,CvSVMParams _params=CvSVMParams() );virtual float predict( const CvMat* _sample ) const;virtual int get_support_vector_count() const;virtual const float* get_support_vector(int i) const;virtual void clear();virtual void save( const char* filename, const char* name=0 );virtual void load( const char* filename, const char* name=0 );virtual void write( CvFileStorage* storage, const char* name );virtual void read( CvFileStorage* storage, CvFileNode* node );int get_var_count() const { return var_idx ? var_idx->cols : var_all; }protected:...};
SVM訓(xùn)練參數(shù)struct
struct CvSVMParams{CvSVMParams();CvSVMParams( int _svm_type, int _kernel_type,double _degree, double _gamma, double _coef0,double _C, double _nu, double _p,CvMat* _class_weights, CvTermCriteria _term_crit );int svm_type;int kernel_type;double degree; // for polydouble gamma; // for poly/rbf/sigmoiddouble coef0; // for poly/sigmoiddouble C; // for CV_SVM_C_SVC, CV_SVM_EPS_SVR and CV_SVM_NU_SVRdouble nu; // for CV_SVM_NU_SVC, CV_SVM_ONE_CLASS, and CV_SVM_NU_SVRdouble p; // for CV_SVM_EPS_SVRCvMat* class_weights; // for CV_SVM_C_SVCCvTermCriteria term_crit; // termination criteria};
svm_type,SVM的類型:
kernel_type//核類型:
degree, gamma, coef0:都是核函數(shù)的參數(shù),具體的參見上面的核函數(shù)的方程。
C, nu, p:在一般的SVM優(yōu)化求解時的參數(shù)。
class_weights: Optional weights, assigned to particular classes. They are multiplied by C and thus affect the mis-classification penalty for different classes. The larger weight, the larger penalty on mis-classification of data from the certain class.
term_crit: Termination procedure for iterative SVM training procedure (which solves a partial case of constrained quadratic optimization problem) The structure needs to be initialized and passed to the training method of CvSVM
訓(xùn)練SVM
bool CvSVM::train( const CvMat* _train_data, const CvMat* _responses,const CvMat* _var_idx=0, const CvMat* _sample_idx=0,CvSVMParams _params=CvSVMParams() );
The method trains SVM model. It follows the conventions of generic train "method" with the following limitations: only CV_ROW_SAMPLE data layout is supported, the input variables are all ordered, the output variables can be either categorical (_params.svm_type=CvSVM::C_SVC or _params.svm_type=CvSVM::NU_SVC) or ordered (_params.svm_type=CvSVM::EPS_SVR or _params.svm_type=CvSVM::NU_SVR) or not required at all (_params.svm_type=CvSVM::ONE_CLASS), missing measurements are not supported.
所有的參數(shù)都被集成在CvSVMParams這個結(jié)構(gòu)中。
得到支撐矢量和特殊矢量的數(shù)
int CvSVM::get_support_vector_count() const;const float* CvSVM::get_support_vector(int i) const;
這個方法可以被用來得到支撐矢量的集合。
雖然從RC1版開始o(jì)pencv開始增設(shè)ML類,提供對常見的分類器和回歸算法的支持。但是尚存在一些問題,比如說例子少(官方許諾說很快會提供一批新例子,見CVS版)。單說SVM這種算法,它自己提供了一套比較完備的函數(shù),但是并不見得優(yōu)于老牌的libsvm(它也應(yīng)該參考過libsvm,至于是否效率優(yōu)于libsvm,我并沒有作過測試,官方也沒有什么說法,但是libsvm持續(xù)開源更新,是公認的現(xiàn)存的開源SVM庫中最易上手,性能最好的庫)。所以在你的程序里整合opencv和libSVM還是一種比較好的解決方案。在VC中整合有些小地方需要注意,這篇文檔主要是提供把圖象作為SVM輸入時程序遇到的這些小問題的解決方案。希望大家遇到問題時,多去讀libSVM的源碼,它本身也是開源的,C代碼寫得也很優(yōu)秀,數(shù)據(jù)結(jié)構(gòu)定義得也比較好。
首先是SVM的訓(xùn)練,這部分我并沒有整合到VC里,直接使用它提供的python程序,雖然網(wǎng)格搜索這種簡易搜索也可以自己寫,但是識別時只需要訓(xùn)練生成的SVMmodel文件即可,所以可以和主程序分離開。至于python在windows下的使用,還是要設(shè)置一下的,首先要在系統(tǒng)環(huán)境變量path里把python的路徑設(shè)進去,libsvm畫訓(xùn)練等高線圖還需要gnuplot的支持,打開python源程序(grid.py),把gnuplot_exe設(shè)置成你機器里的安裝路徑,這樣才能正確的運行程序。然後就是改步長和搜索范圍,官方建議是先用大步長搜索,搜到最優(yōu)值後再用小步長在小范圍內(nèi)搜索(我覺得這有可能會陷入局部最優(yōu),不過近似出的結(jié)果還可以接受)。我用的python版本是2.4,gnuplot4.0。
官方站點,有一些tutorial和測試數(shù)據(jù)
上交的一個研究生還寫過libsvm2.6版的代碼中文注釋,源鏈接找不著了,大家自己搜搜吧,寫得很好,上海交通大學(xué)模式分析與機器智能實驗室。