對於功能這麼強的算法,OpenCV中天然也是有集成好了,咱們能夠直接調用。OpenCV中的SVM算法是基於LibSVM軟件包開發的,LibSVM是臺灣大學林智仁(Lin Chih-Jen)等開發設計的一個簡單、易於使用和快速有效的SVM模式識別與迴歸的軟件包。算法
網上講opencv中SVM使用的文章有不少,但講SVM參數優化的文章卻不多。因此在這裏不重點講怎麼使用SVM,而是談談怎樣經過opencv中自帶的庫優化SVM中的各參數。
相信用SVM作過實驗的人都知道,SVM的各參數對實驗結果有很大的影響,好比C,gama,P,coef等等。下面就是CvSVMParams類的原型。數據結構
C++: CvSVMParams::CvSVMParams()機器學習
C++: CvSVMParams::CvSVMParams(int svm_type, 函數
int kernel_type, 學習
)
<1>
svm_type:指定SVM的類型(5種):
- CvSVM::C_SVC : C類支持向量分類機。 n類分組 (n≥2),容許用異常值懲罰因子C進行不徹底分類。
- CvSVM::NU_SVC :
類支持向量分類機。n相似然不徹底分類的分類器。參數爲
取代C(其值在區間【0,1】中,nu越大,決策邊界越平滑)。
- CvSVM::ONE_CLASS : 單分類器,全部的訓練數據提取自同一個類裏,而後SVM創建了一個分界線以分割該類在特徵空間中所佔區域和其它類在特徵空間中所佔區域。
- CvSVM::EPS_SVR :
類支持向量迴歸機。訓練集中的特徵向量和擬合出來的超平面的距離須要小於p。異常值懲罰因子C被採用。
- CvSVM::NU_SVR :
類支持向量迴歸機。
代替了 p。
<2>kernel_type:SVM的內核類型(4種):
- CvSVM::LINEAR : 線性內核,沒有任何向映射至高維空間,線性區分(或迴歸)在原始特徵空間中被完成,這是最快的選擇。
![](http://static.javashuo.com/static/loading.gif)
.
![](http://static.javashuo.com/static/loading.gif)
.
- CvSVM::RBF : 基於徑向的函數,對於大多數狀況都是一個較好的選擇:
![](http://static.javashuo.com/static/loading.gif)
.
- CvSVM::SIGMOID : Sigmoid函數內核:
![](http://static.javashuo.com/static/loading.gif)
.
<3>
degree:內核函數(POLY)的參數degree。
<4>
gamma:內核函數(POLY/ RBF/ SIGMOID)的參數
![](http://static.javashuo.com/static/loading.gif)
。
<5>
coef0:內核函數(POLY/ SIGMOID)的參數coef0。
<6>
Cvalue:SVM類型(C_SVC/ EPS_SVR/ NU_SVR)的參數C。
<7>
nu:SVM類型(NU_SVC/ ONE_CLASS/ NU_SVR)的參數
![](http://static.javashuo.com/static/loading.gif)
。
<8>
p:SVM類型(EPS_SVR)的參數
![](http://static.javashuo.com/static/loading.gif)
。
<9>
class_weights:C_SVC中的可選權重,賦給指定的類,乘以C之後變成
![](http://static.javashuo.com/static/loading.gif)
。因此這些權重影響不一樣類別的錯誤分類懲罰項。權重越大,某一類別的誤分類數據的懲罰項就越大。
<10>
term_crit:SVM的迭代訓練過程的停止條件,解決部分受約束二次最優問題。您能夠指定的公差和/或最大迭代次數。
固然對於一個特定的SVM訓練器,裏面的全部參數不必定全用。好比我用的svm_type爲EPS_SVR,那麼我要用到的參數主要就是p,c,gama這三個參數。下面是設置參數的代碼
- CvSVMParams param;
- param.svm_type = CvSVM::EPS_SVR;
- param.kernel_type = CvSVM::RBF;
- param.C = 1;
- param.p = 5e-3;
- param.gamma = 0.01;
- param.term_crit = cvTermCriteria(CV_TERMCRIT_EPS, 100, 5e-3);
設置參數後就能夠用CvSVM.train()進行訓練了,下面是train的原型
C++: bool CvSVM::train(const Mat& trainData,
const Mat& responses,
const Mat& sampleIdx=Mat(),
CvSVMParams params=CvSVMParams()
我在用train完成訓練預測時出現了過擬合的狀況,即對於訓練集的數據有很好的預測結果,但對不在訓練集的測試集預測值都同樣(我在網上看到不少網友也遇到這個問題)。因而我開始調整參數,調了半天也沒個好結果。
後面我發現其實opencv中SVM類是提供了優化參數值功能的,瞬間感受世界美好了。下面講講具體的作法。
要讓svm自動優化參數,那麼訓練時就不能再用train函數了,而應該用train_auto函數。下面是train_auto的函數原型
C++: bool CvSVM::train_auto(const Mat& trainData,
const Mat& responses,
const Mat& varIdx,
const Mat& sampleIdx,
CvSVMParams params,
int k_fold=10,
CvParamGrid Cgrid=CvSVM::get_default_grid(CvSVM::C), CvParamGrid gammaGrid=CvSVM::get_default_grid(CvSVM::GAMMA), CvParamGrid pGrid=CvSVM::get_default_grid(CvSVM::P), CvParamGrid nuGrid=CvSVM::get_default_grid(CvSVM::NU), CvParamGrid coeffGrid=CvSVM::get_default_grid(CvSVM::COEF), CvParamGrid degreeGrid=CvSVM::get_default_grid(CvSVM::DEGREE),
bool balanced=false
)
自動訓練函數的參數註釋(13個)
- 前5個參數參考構造函數的參數註釋。
- k_fold: 交叉驗證參數。訓練集被分紅k_fold的自子集。其中一個子集是用來測試模型,其餘子集則成爲訓練集。因此,SVM算法複雜度是執行k_fold的次數。
- *Grid: (6個)對應的SVM迭代網格參數。
- balanced: 若是是true則這是一個2類分類問題。這將會建立更多的平衡交叉驗證子集。
自動訓練函數的使用說明
- 這個方法根據CvSVMParams中的最佳參數C, gamma, p, nu, coef0, degree自動訓練SVM模型。
- 參數被認爲是最佳的交叉驗證,其測試集預估錯誤最小。
- 若是沒有須要優化的參數,相應的網格步驟應該被設置爲小於或等於1的值。例如,爲了不gamma的優化,設置gamma_grid.step = 0,gamma_grid.min_val, gamma_grid.max_val 爲任意數值。因此params.gamma 由gamma得出。
- 最後,若是參數優化是必需的,可是相應的網格卻不肯定,你可能須要調用函數CvSVM::get_default_grid(),建立一個網格。例如,對於gamma,調用CvSVM::get_default_grid(CvSVM::GAMMA)。
- 該函數爲分類運行 (params.svm_type=CvSVM::C_SVC 或者 params.svm_type=CvSVM::NU_SVC) 和爲迴歸運行 (params.svm_type=CvSVM::EPS_SVR 或者 params.svm_type=CvSVM::NU_SVR)效果同樣好。若是params.svm_type=CvSVM::ONE_CLASS,沒有優化,並指定執行通常的SVM。
這裏須要注意的是,對於須要的優化的參數雖然train_auto能夠自動選擇最優值,但在代碼中也要先賦初始值,要否則編譯能經過,但運行時會報錯。下面是示例代碼
- CvSVMParams param;
- param.svm_type = CvSVM::EPS_SVR;
- param.kernel_type = CvSVM::RBF;
- param.C = 1;
- param.p = 5e-3;
- param.gamma = 0.01;
- param.term_crit = cvTermCriteria(CV_TERMCRIT_EPS, 100, 5e-3);
- CvParamGrid nuGrid = CvParamGrid(1,1,0.0);
- CvParamGrid coeffGrid = CvParamGrid(1,1,0.0);
- CvParamGrid degreeGrid = CvParamGrid(1,1,0.0);
-
- CvSVM regressor;
- regressor.train_auto(PCA_training,tr_label,NULL,NULL,param,
- 10,
- regressor.get_default_grid(CvSVM::C),
- regressor.get_default_grid(CvSVM::GAMMA),
- regressor.get_default_grid(CvSVM::P),
- nuGrid,
- coeffGrid,
- degreeGrid);
用上面的代碼的就能夠自動訓練並優化參數。最後,若想查看優化後的參數值,可使用CvSVM::get_params()函數來得到優化後的CvSVMParams。下面是示例代碼:
- CvSVMParams params_re = regressor.get_params();
- regressor.save("training_srv.xml");
- float C = params_re.C;
- float P = params_re.p;
- float gamma = params_re.gamma;
- printf("\nParms: C = %f, P = %f,gamma = %f \n",C,P,gamma);
本文系原創,轉載請註明轉載自 http://blog.csdn.net/computerme/article/details/38677599