?? 機器學習中文參考手冊 - opencv china.htm
字號:
cvSet( &trainClasses1, cvScalar(1) );
cvGetRows( trainClasses, &trainClasses2, train_sample_count/2, train_sample_count );
cvSet( &trainClasses2, cvScalar(2) );
// learn classifier
CvKNearest knn( trainData, trainClasses, 0, false, K );
CvMat* nearests = cvCreateMat( 1, K, CV_32FC1);
for( i = 0; i < img->height; i++ )
{
for( j = 0; j < img->width; j++ )
{
sample.data.fl[0] = (float)j;
sample.data.fl[1] = (float)i;
// estimates the response and get the neighbors' labels
response = knn.find_nearest(&sample,K,0,0,nearests,0);
// compute the number of neighbors representing the majority
for( k = 0, accuracy = 0; k < K; k++ )
{
if( nearests->data.fl[k] == response)
accuracy++;
}
// highlight the pixel depending on the accuracy (or confidence)
cvSet2D( img, i, j, response == 1 ?
(accuracy > 5 ? CV_RGB(180,0,0) : CV_RGB(180,120,0)) :
(accuracy > 5 ? CV_RGB(0,180,0) : CV_RGB(120,120,0)) );
}
}
// display the original training samples
for( i = 0; i < train_sample_count/2; i++ )
{
CvPoint pt;
pt.x = cvRound(trainData1.data.fl[i*2]);
pt.y = cvRound(trainData1.data.fl[i*2+1]);
cvCircle( img, pt, 2, CV_RGB(255,0,0), CV_FILLED );
pt.x = cvRound(trainData2.data.fl[i*2]);
pt.y = cvRound(trainData2.data.fl[i*2+1]);
cvCircle( img, pt, 2, CV_RGB(0,255,0), CV_FILLED );
}
cvNamedWindow( "classifier result", 1 );
cvShowImage( "classifier result", img );
cvWaitKey(0);
cvReleaseMat( &trainClasses );
cvReleaseMat( &trainData );
return 0;
}
</PRE>
<DIV class=editsection style="FLOAT: right; MARGIN-LEFT: 5px">[<A
title=機器學習中文參考手冊
href="http://www.opencv.org.cn/index.php?title=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%B8%AD%E6%96%87%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C&action=edit&section=22">編輯</A>]</DIV><A
name=.E6.94.AF.E6.92.91.E5.90.91.E9.87.8F.E6.9C.BA.E9.83.A8.E5.88.86></A>
<H1>支撐向量機部分 </H1>
<P>支撐向量機(SVM),起初由vapnik提出時,是作為尋求最優(在一定程度上)二分類器的一種技術。後來它又被拓展到回歸和聚類應用。SVM是一種基于核函數的方法,它通過某些核函數把特征向量映射到高維空間,然後建立一個線性判別函數(或者說是一個高維空間中的能夠區分訓練數據的最優超平面,參考異或那個經典例子)。假如SVM沒有明確定義核函數,高維空間中任意兩點距離就需要定義。
</P>
<P>解是最優的在某種意義上是兩類中距離分割面最近的特征向量和分割面的距離最大化。離分割面最近的特征向量被稱為”支撐向量”,意即其它向量不影響分割面(決策函數)。
</P>
<P>有很多關于SVM的參考文獻,這是兩篇較好的入門文獻。 </P>
<P>【Burges98】 C. Burges. "A tutorial on support vector machines for pattern
recognition", Knowledge Discovery and Data Mining 2(2), 1998. (available online
at <A class="external autonumber"
title=http://citeseer.ist.psu.edu/burges98tutorial.html
href="http://citeseer.ist.psu.edu/burges98tutorial.html" rel=nofollow>[1]</A>).
</P>
<P>LIBSVM - A Library for Support Vector Machines. By Chih-Chung Chang and
Chih-Jen Lin (<A class="external autonumber"
title=http://www.csie.ntu.edu.tw/~cjlin/libsvm/
href="http://www.csie.ntu.edu.tw/~cjlin/libsvm/" rel=nofollow>[2]</A>) </P>
<DIV class=editsection style="FLOAT: right; MARGIN-LEFT: 5px">[<A
title=機器學習中文參考手冊
href="http://www.opencv.org.cn/index.php?title=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%B8%AD%E6%96%87%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C&action=edit&section=23">編輯</A>]</DIV><A
name=CvSVM></A>
<H2>CvSVM</H2>
<P>支撐矢量機 </P><PRE>class CvSVM : public CvStatModel //繼承自基類CvStatModel
{
public:
// SVM type
enum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 };//SVC是SVM分類器,SVR是SVM回歸
// SVM kernel type
enum { LINEAR=0, POLY=1, RBF=2, SIGMOID=3 }; //提供四種核函數,分別是線性,多項式,徑向基,sigmoid型函數。
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:
...
};
</PRE>
<DIV class=editsection style="FLOAT: right; MARGIN-LEFT: 5px">[<A
title=機器學習中文參考手冊
href="http://www.opencv.org.cn/index.php?title=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%B8%AD%E6%96%87%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C&action=edit&section=24">編輯</A>]</DIV><A
name=CvSVMParams></A>
<H2>CvSVMParams</H2>
<P>SVM訓練參數struct </P><PRE>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 poly
double gamma; // for poly/rbf/sigmoid
double coef0; // for poly/sigmoid
double C; // for CV_SVM_C_SVC, CV_SVM_EPS_SVR and CV_SVM_NU_SVR
double nu; // for CV_SVM_NU_SVC, CV_SVM_ONE_CLASS, and CV_SVM_NU_SVR
double p; // for CV_SVM_EPS_SVR
CvMat* class_weights; // for CV_SVM_C_SVC
CvTermCriteria term_crit; // termination criteria
};
</PRE>
<P>svm_type,SVM的類型: </P>
<DL>
<DD>CvSVM::C_SVC - n(n>=2)分類器,允許用異常值懲罰因子C進行不完全分類。
<DD>CvSVM::NU_SVC - n類似然不完全分類的分類器。參數nu取代了c,其值在區間【0,1】中,nu越大,決策邊界越平滑。
<DD>CvSVM::ONE_CLASS -
單分類器,所有的訓練數據提取自同一個類里,然後SVM建立了一個分界線以分割該類在特征空間中所占區域和其它類在特征空間中所占區域。
<DD>CvSVM::EPS_SVR - 回歸。 訓練集中的特征向量和擬合出來的超平面的距離需要小于p。異常值懲罰因子C被采用。
<DD>CvSVM::NU_SVR - 回歸;nu 代替了p </DD></DL>
<P>kernel_type//核類型: </P>
<DL>
<DD>CvSVM::LINEAR - 沒有任何向映射至高維空間,線性區分(或回歸)在原始特征空間中被完成,這是最快的選擇。 d(x,y) = x?y ==
(x,y)
<DD>CvSVM::POLY - 多項式核: d(x,y) = (gamma*(x?y)+coef0)degree
<DD>CvSVM::RBF - 徑向基,對于大多數情況都是一個較好的選擇:d(x,y) = exp(-gamma*|x-y|2)
<DD>CvSVM::SIGMOID - sigmoid函數被用作核函數: d(x,y) = tanh(gamma*(x?y)+coef0)
</DD></DL>
<P>degree, gamma, coef0:都是核函數的參數,具體的參見上面的核函數的方程。 </P>
<P>C, nu, p:在一般的SVM優化求解時的參數。 </P>
<P>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. </P>
<P>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
</P>
<DIV class=editsection style="FLOAT: right; MARGIN-LEFT: 5px">[<A
title=機器學習中文參考手冊
href="http://www.opencv.org.cn/index.php?title=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%B8%AD%E6%96%87%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C&action=edit&section=25">編輯</A>]</DIV><A
name=CvSVM::train></A>
<H2>CvSVM::train</H2>
<P>訓練SVM </P><PRE>bool CvSVM::train( const CvMat* _train_data, const CvMat* _responses,
const CvMat* _var_idx=0, const CvMat* _sample_idx=0,
CvSVMParams _params=CvSVMParams() );
</PRE>
<P>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.
</P>
<P>所有的參數都被集成在CvSVMParams這個結構中。 </P>
<P><BR></P>
<DIV class=editsection style="FLOAT: right; MARGIN-LEFT: 5px">[<A
title=機器學習中文參考手冊
href="http://www.opencv.org.cn/index.php?title=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%B8%AD%E6%96%87%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C&action=edit&section=26">編輯</A>]</DIV><A
name=CvSVM::get_support_vector.2A></A>
<H2>CvSVM::get_support_vector*</H2>
<P>得到支撐矢量和特殊矢量的數 </P><PRE>int CvSVM::get_support_vector_count() const;
const float* CvSVM::get_support_vector(int i) const;
</PRE>
<P>這個方法可以被用來得到支撐矢量的集合。 </P>
<DIV class=editsection style="FLOAT: right; MARGIN-LEFT: 5px">[<A
title=機器學習中文參考手冊
href="http://www.opencv.org.cn/index.php?title=%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%B8%AD%E6%96%87%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C&action=edit&section=27">編輯</A>]</DIV><A
name=.E8.A1.A5.E5.85.85:.E5.9C.A8WindowsXP.2BOpenCVRC1.E5.B9.B3.E5.8F.B0.E4.B8.8B.E6.95.B4.E5.90.88OpenCV.E4.B8.8ElibSVM></A>
<H2>補充:在WindowsXP+OpenCVRC1平臺下整合OpenCV與libSVM </H2>
<P>雖然從RC1版開始opencv開始增設ML類,提供對常見的分類器和回歸算法的支持。但是尚存在一些問題,比如說例子少(官方許諾說很快會提供一批新例子,見CVS版)。單說SVM這種算法,它自己提供了一套比較完備的函數,但是并不見得優于老牌的libsvm(它也應該參考過libsvm,至于是否效率優于libsvm,我并沒有作過測試,官方也沒有什么說法,但是libsvm持續開源更新,是公認的現存的開源SVM庫中最易上手,性能最好的庫)。所以在你的程序里整合opencv和libSVM還是一種比較好的解決方案。在VC中整合有些小地方需要注意,這篇文檔主要是提供把圖象作為SVM輸入時程序遇到的這些小問題的解決方案。希望大家遇到問題時,多去讀libSVM的源碼,它本身也是開源的,C代碼寫得也很優秀,數據結構定義得也比較好。
</P>
<P>首先是SVM的訓練,這部分我并沒有整合到VC里,直接使用它提供的python程序,雖然網格搜索這種簡易搜索也可以自己寫,但是識別時只需要訓練生成的SVMmodel文件即可,所以可以和主程序分離開。至于python在windows下的使用,還是要設置一下的,首先要在系統環境變量path里把python的路徑設進去,libsvm畫訓練等高線圖還需要gnuplot的支持,打開python源程序(grid.py),把gnuplot_exe設置成你機器里的安裝路徑,這樣才能正確的運行程序。然後就是改步長和搜索范圍,官方建議是先用大步長搜索,搜到最優值後再用小步長在小范圍內搜索(我覺得這有可能會陷入局部最優,不過近似出的結果還可以接受)。我用的python版本是2.4,gnuplot4.0。
</P>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -