1. 程式人生 > >OpenCV中的SVM引數優化

OpenCV中的SVM引數優化

轉載自http://blog.csdn.net/computerme/article/details/38677599

SVM(支援向量機)是機器學習演算法裡用得最多的一種演算法。SVM最常用的是用於分類,不過SVM也可以用於迴歸,我的實驗中就是用SVM來實現SVR(支援向量迴歸)。

    對於功能這麼強的演算法,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

double degree

double gamma

double coef0

double Cvalue

double nu,                   

double p

CvMat* class_weights,

CvTermCriteria term_crit

        )

<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 : 線性核心,沒有任何向對映至高維空間,線性區分(或迴歸)在原始特徵空間中被完成,這是最快的選擇。
            .
  • CvSVM::POLY : 多項式核心:
             .
  • CvSVM::RBF : 基於徑向的函式,對於大多數情況都是一個較好的選擇:
             .
  • CvSVM::SIGMOID : Sigmoid函式核心:
            . <3>degree:核心函式(POLY)的引數degree。 <4>gamma:核心函式(POLY/ RBF/ SIGMOID)的引數。 <5>coef0:核心函式(POLY/ SIGMOID)的引數coef0。 <6>Cvalue:SVM型別(C_SVC/ EPS_SVR/ NU_SVR)的引數C。 <7>nu:SVM型別(NU_SVC/ ONE_CLASS/ NU_SVR)的引數 。 <8>p:SVM型別(EPS_SVR)的引數。 <9>class_weights:C_SVC中的可選權重,賦給指定的類,乘以C以後變成 。所以這些權重影響不同類別的錯誤分類懲罰項。權重越大,某一類別的誤分類資料的懲罰項就越大。 <10>term_crit:SVM的迭代訓練過程的中止條件,解決部分受約束二次最優問題。您可以指定的公差和/或最大迭代次數。     當然對於一個特定的SVM訓練器,裡面的所有引數不一定全用。比如我用的svm_type為EPS_SVR,那麼我要用到的引數主要就是p,c,gama這三個引數。下面是設定引數的程式碼 [cpp] view plain copy print?
  1. CvSVMParams param;    
  2. param.svm_type = CvSVM::EPS_SVR;  //我的實驗是用SVR作迴歸分析,可能大部分人的實驗是用SVM來分類,方法都一樣
  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);   
	CvSVMParams param;  
	param.svm_type = CvSVM::EPS_SVR;  //我的實驗是用SVR作迴歸分析,可能大部分人的實驗是用SVM來分類,方法都一樣
	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& varIdx=Mat()

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可以自動選擇最優值,但在程式碼中也要先賦初始值,要不然編譯能通過,但執行時會報錯。下面是示例程式碼 [cpp] 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. CvSVM regressor;  
  13. regressor.train_auto(PCA_training,tr_label,NULL,NULL,param,  
  14.     10,  
  15.     regressor.get_default_grid(CvSVM::C),  
  16.     regressor.get_default_grid(CvSVM::GAMMA),  
  17.     regressor.get_default_grid(CvSVM::P),  
  18.     nuGrid,  
  19.     coeffGrid,  
  20.     degreeGrid);  
	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); 
	//對不用的引數step設為0
	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。下面是示例程式碼: [cpp] 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);  
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

相關推薦

OPENCVSVM引數解析--學習1

先來看一下什麼是SVM(支援向量機) SVM是一種訓練機器學習的演算法,可以用於解決分類和迴歸問題,同時還使用了一種稱之為kernel trick(支援向量機的核函式)的技術進行資料的轉換,然後再根據這些轉換資訊,在可能的輸出之中找到一個最優的邊界(超平面)。簡單來說,就是做一些非常複雜的資料轉換工作,然

OpenCVSVM引數優化

轉載自http://blog.csdn.net/computerme/article/details/38677599 SVM(支援向量機)是機器學習演算法裡用得最多的一種演算法。SVM最常用的是用於分類,不過SVM也可以用於迴歸,我的實驗中就是用SVM來實現SVR(支援向

opencvmask引數

其實opencv 裡面很多函式都是會帶有一個mask 引數的,很多同學都不知道它到底有什麼用,好像在實際運用中忽略它也沒有什麼問題(這不廢話嘛,opencv設計師設計它的時候預設就是可以忽略的)。 我在這裡就拋磚引玉,詳細分析一個常用函式cvcopy裡面的mas

opencv SVM + PCA 人臉識別

這一週一直都在弄人臉識別的東西,這個也可以算是我個人第一個DIY專案,雖然沒有在MFC框架下來實現,但我覺得 SVM + PCA 人臉識別這個東西 最主要的還是演算法 和效果沒有必要一定要在MFC框架下去實現。 從不懂到慢慢明白一些道理,寫這樣一個技術文件無非就是怕以後忘記這樣一個過程。 從這個專案得到的經驗

opencvsvm引數說明

svm_type,SVM的型別: CvSVM::C_SVC - n(n>=2)分類器,允許用異常值懲罰因子C進行不完全分類。 CvSVM::NU_SVC - n類似然不完全分類的分類器。引數nu取代了c,其值在區間【0,1】中,nu越大,決策邊界越平滑。 CvSV

SKLearnSVM引數自動選擇的最簡單示例(使用GridSearchCV)

大家都知道,SVM如果在調參比較好的情況下,可以達到很好的分類效果,不過SVM也確實引數比較多,例如在這裡介紹的:也有些朋友對調參過程做了比較詳細的解釋:據網友介紹,SVM調參過程中應主要調kernel,C 和gamma,對於SKLearn,我們可以使用GridSearchC

OpencvSVM樣本訓練、歸類流程及實現

支援向量機(SVM)中最核心的是什麼?個人理解就是前4個字——“支援向量”,一旦在兩類或多累樣本集中定位到某些特定的點作為支援向量,就可以依據這些支援向量計算出來分類超平面,再依據超平面對類別進行歸類劃分就是水到渠成的事了。有必要回顧一下什麼是支援向量機中的支援向量。

opencvSVM圖像分類(二)

proc 文本 c_str lec 源碼 open right tle 特征描述 opencv中的SVM圖像分類(二) 標簽: svm圖像 2015-07-30 08:45 8296人閱讀 評論(35) 收藏 舉報 分類: 【opencv應用】(5) 版

解決一個Ubuntu編譯NEON優化OpenCV的錯誤

asm pre neon iat tar 查詢 avg mpi 安裝 在Ubuntu 16中編譯開啟NEON優化的Opencv時,遇到libpng編譯是使用匯編代碼的錯誤,完整錯誤見文章末尾。通過查詢發現解決方案是安裝跨平臺編譯器,安裝代碼如下: sudo apt-get

OpenCV對split的優化方法

目錄 1.問題 2.思路 3.實現 4.資料   1.問題 問題源於:http://answers.opencv.org/question/109754/optimizing-splitmerge-for-clahe/ 具體: 提問者在做限制性對比度

opencv——SVM引數詳解

         SVM是一種訓練機器學習的演算法,可以用於解決分類和迴歸問題,同時還使用了一種稱之為kernel trick(支援向量機的核函式)的技術進行資料的轉換,然後再根據這些轉換資訊,在可能的輸出之中找到一個最優的邊界(超平面)。簡單來說,

關於opencv訓練級聯分類器所使用opencv_createsamples.exe和opencv_traincascade.exe的引數的詳細說明

關於如何訓練分類器來識別一個新目標,可以看這裡。 重點注意事項: OpenCV中有兩個程式可以訓練級聯分類器: opencv_haartraining and opencv_traincascade。opencv_traincascade 是一個新程式,使用Op

SVM引數引數介紹以及python實現GA對SVM引數優化

  最近開始玩起了機器學習,以前都是用matlab做一些機器學習的東西,畢竟要真正放到工程上應用還是python用起來比較好,所以今天就開始學習下使用SVM進行迴歸(分類)預測。 SVM 使用的一般步驟是: 1)準備資料集,轉化為 SVM支援的資料格式 : [label] [ind

Opencv CV_8UC1,CV_32FC3等引數的含義

      示例:   CV_<bit_depth>(S|U|F)C<number_of_channels>         1--bit_depth---位元數---代表8bite,16bites,32bites,64bites---舉個例子

python資料分析:商品資料化運營()——基於引數優化的Gradient Boosting的銷售預測

本案例需要使用超引數交叉檢驗和優化方法GridSearchCV以及整合迴歸方法GradientBoostingRegressor GridSearchCV與GradientBoostingRegressor GridSearchCV GridSearchCV用於系統地遍歷多種

opencv、機器學習】opencvSVM影象分類(二)

上一篇博文對影象分類理論部分做了比較詳細的講解,這一篇主要是對影象分類程式碼的實現進行分析。理論部分我們談到了使用BOW模型,但是BOW模型如何構建以及整個步驟是怎麼樣的呢?可以參考下面的部落格http://www.cnblogs.com/yxy8023ustc/p/33

OpenCV的HOG+SVM物體分類

這裡總結網上自己找到的資料,搞一個簡單的框架供大家參考一下。 [cpp] view plaincopyprint? [cpp] view plaincopyprint  #include "cv.h"   #include "highgui.h"  

opencv、機器學習】opencvSVM影象分類(一)

一、影象分類概述 本模組是用在影象內容識別的部分,影象分類是利用計算機對影象進行定量分析,把影象中的每個像元或區域劃歸為若干個類別中的一種,以代替人工視覺判讀的技術。從目視角度來說,對影象進行提高對比度、增加視覺維數、進行空間濾波或變換等處理的目的就是使人們能夠憑藉知識

Gabor濾波簡介與Opencv的實現及引數變化實驗

Gabor濾波是一種非常常見的特徵提取演算法,在人臉識別等領域有著很廣泛的應用,在這裡我主要介紹一下Gabor濾波器的公式及Opencv下的程式碼實現,以及我做的一些引數變化的實驗。 一、Gabor濾波簡介 注意,這裡我介紹的Gabor演算法與在人臉識別

【Machine Learning】【Python】三、PSO + PCA優化SVM引數C和gamma ---- 《SVM物體分類和定位檢測》

---------------------【6.27 更新libsvm使用方法】-------------------------------------------------------------