svm 中采用自動搜索參數的方式獲得參數值


載時自http://blog.csdn.net/u011177305/article/details/46458801?locationNum=1

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

)

 

自動訓練函數的使用說明:
這個方法根據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。

參考IT修道者博文的文章,使用其如下代碼

 

[html]  view plain  copy
 
 print?
  1. CvSVMParams param;    
  2.   param.svm_type = CvSVM::EPS_SVR;    
  3.   param.kernel_type = CvSVM::RBF;    
  4.   param.C = 1;  //給參數賦初始值  
  5.   param.p = 5e-3;  //給參數賦初始值  
  6.   param.gamma = 0.01;  //給參數賦初始值  
  7.   param.term_crit = cvTermCriteria(CV_TERMCRIT_EPS, 100, 5e-3);   
  8.   //對不用的參數step設為0  
  9.   CvParamGrid nuGrid = CvParamGrid(1,1,0.0);  
  10.   CvParamGrid coeffGrid = CvParamGrid(1,1,0.0);  
  11.   CvParamGrid degreeGrid = CvParamGrid(1,1,0.0);  
  12.   
  13.   CvSVM regressor;  
  14.   regressor.train_auto(PCA_training,tr_label,NULL,NULL,param,  
  15.     10,  
  16.     regressor.get_default_grid(CvSVM::C),  
  17.     regressor.get_default_grid(CvSVM::GAMMA),  
  18.     regressor.get_default_grid(CvSVM::P),  
  19.     nuGrid,  
  20.     coeffGrid,  
  21.     degreeGrid);  
用上面的代碼的就可以自動訓練優化出參數了,最后想查看優化后的參數值可以使用CvSVMParams params_re = regressor.get_params()函數來獲得各優化后的參數值。

 

 

[html]  view plain  copy
 
 print?
  1. CvSVMParams params_re = regressor.get_params();  
  2.   regressor.save("training_srv.xml");  
  3.   float C = params_re.C;  
  4.   float P = params_re.p;  
  5.   float gamma = params_re.gamma;  
  6.   printf("\nParms: C = %f, P = %f,gamma = %f \n",C,P,gamma);  
不過根據我的測試發現如下錯誤:
OpenCV Error: Assertion failed (sv_count != 0) in do_train, file /home/.../opencv-2.4.9/modules/ml/src/svm.cpp, line 1346

 

該問題在stack overflow中有人提出,不過沒有解決方案。

我修改了一下

 

CvParamGrid CvParamGrid_C(pow(2.0,-5), pow(2.0,15), pow(2.0,2)); CvParamGrid CvParamGrid_gamma(pow(2.0,-15), pow(2.0,3), pow(2.0,2)); if (!CvParamGrid_C.check() || !CvParamGrid_gamma.check()) cout<<"The grid is NOT VALID."<<endl; CvSVMParams paramz; paramz.kernel_type = CvSVM::RBF; paramz.svm_type = CvSVM::C_SVC; paramz.term_crit = cvTermCriteria(CV_TERMCRIT_ITER,100,0.000001); svm.train_auto(trainingData, labels, Mat(), Mat(), paramz,10, CvParamGrid_C, CvParamGrid_gamma, CvSVM::get_default_grid(CvSVM::P), CvSVM::get_default_grid(CvSVM::NU), CvSVM::get_default_grid(CvSVM::COEF), CvSVM::get_default_grid(CvSVM::DEGREE), true); paramz = svm.get_params(); cout<<"gamma:"<<paramz.gamma<<endl; cout<<"C:"<<paramz.C<<endl;
大家不妨嘗試一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM