Opencv中SVM的使用问题
2015-04-16 21:18
316 查看
CvSVM svm;// = CvSVM();//新建一个SVM CvSVMParams param;//这里是参数 CvTermCriteria criteria; criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON ); param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria ); /* SVM种类:CvSVM::C_SVC Kernel的种类:CvSVM::RBF degree:10.0(此次不使用) gamma:8.0 coef0:1.0(此次不使用) C:10.0 nu:0.5(此次不使用) p:0.1(此次不使用) 然后对训练数据正规化处理,并放在CvMat型的数组里。 */ //☆☆☆☆☆☆☆☆☆(5)SVM学习☆☆☆☆☆☆☆☆☆☆☆☆ svm.train( data_mat, res_mat, NULL, NULL, param );//训练啦 //☆☆利用训练数据和确定的学习参数,进行SVM学习☆☆☆☆ svm.save( "SVM_DATA.xml" );
1.首先声明一个CvSVM类
2.OpenCV学习–cvTermCriteria介绍
<pre name="code" class="cpp">CvTermCriteria 迭代算法的终止准则 #define CV_TERMCRIT_ITER 1 #define CV_TERMCRIT_NUMBER CV_TERMCRIT_ITER #define CV_TERMCRIT_EPS 2 typedef struct CvTermCriteria { int type; /* CV_TERMCRIT_ITER 和CV_TERMCRIT_EPS二值之一,或者二者的组合 */ int max_iter; /* 最大迭代次数 */ double epsilon; /* 结果的精确性 */ } CvTermCriteria; /* 构造函数 */ inline CvTermCriteria cvTermCriteria( int type, int max_iter, double epsilon ); /* 在满足max_iter和epsilon的条件下检查终止准则并将其转换使得type=CV_TERMCRIT_ITER+CV_TERMCRIT_EPS */ CvTermCriteria cvCheckTermCriteria( CvTermCriteria criteria, double default_eps, int default_max_iters );
3.Opencv中的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
)
4.样本train
设置参数后就可以用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可以自动选择最优值,但在代码中也要先赋初始值,要不然编译能通过,但运行时会报错。 下面是示例代码
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);
用上面的代码的就可以自动训练优化出参数了,最后想查看优化后的参数值可以使用CvSVMParams
params_re = regressor.get_params()函数来获得各优化后的参数值
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);
======================================================
用OpenCV使用SVM算法的大概流程是
1)设置训练样本集
需要两组数据,一组是数据的类别,一组是数据的向量信息。
2)设置SVM参数
利用CvSVMParams类实现类中的成员变量svm_type表示SVM类型:
CvSVM::C_SVC C-SVC
CvSVM::NU_SVC v-SVC
CvSVM::ONE_CLASS 一类SVM
CvSVM::EPS_SVR e-SVR
CvSVM::NU_SVR v-SVR
成员变量kernel_type表示核函数的类型:
CvSVM::LINEAR 线性:u‘v
CvSVM::POLY 多项式:(r*u'v + coef0)^degree
CvSVM::RBF RBF函数:exp(-r|u-v|^2)
CvSVM::SIGMOID sigmoid函数:tanh(r*u'v + coef0)
成员变量degree针对多项式核函数degree的设置
gamma针对多项式/rbf/sigmoid核函数的设置
coef0针对多项式/sigmoid核函数的设置
Cvalue为损失函数
在C-SVC、e-SVR、v-SVR中有效,nu设置v-SVC、一类SVM和v-SVR参数
p为设置e-SVR中损失函数的值
class_weightsC_SVC的权重
term_crit为SVM训练过程的终止条件。
其中默认值degree = 0,gamma = 1,coef0 = 0,Cvalue = 1,nu = 0,p = 0,class_weights = 0
3)训练SVM
调用CvSVM::train函数建立SVM模型,第一个参数为训练数据,第二个参数为分类结果,最后一个参数即CvSVMParams
4)用这个SVM进行分类
调用函数CvSVM::predict实现分类
CvSVM::predict用来预测一个新样本的响应值,在分类器问题中,这个函数返回类别编号,在回归问题中,返回函数值。
另外:
对输入图片进行行人检测时由于图片的大小不一样,所以要用到多尺度检测。这里是用hog类的方法detectMultiScale。参数解释如下:
HOGDescriptor::detectMultiScale(const
GpuMat& img,
vector<Rect>& found_locations,
doublehit_threshold=0,
Size win_stride=Size(),
Size padding=Size(),
double scale0=1.05,
int group_threshold=2)
myHOG.detectMultiScale(src, found, 0, Size(8,8), Size(32,32), 1.05, 2);//对图片进行多尺度行人检测该函数表示对输入的图片img进行多尺度行人检测 img为输入待检测的图片;found_locations为检测到目标区域列表;参数3为程序内部计算为行人目标的阈值,也就是检测到的特征到SVM分类超平面的距离;参数4为滑动窗口每次移动的距离。它必须是块移动的整数倍;参数5为图像扩充的大小;参数6为比例系数,即滑动窗口每次增加的比例;参数7为组阈值,即校正系数,当一个目标被多个窗口检测出来时,该参数此时就起了调节作用,为0时表示不起调节作用。
5)获得支持向量
除了分类,也可以得到SVM的支持向量,调用函数CvSVM::get_support_vector_count获得支持向量的个数,
CvSVM::get_support_vector获得对应的索引编号的支持向量。
6)获取决策函数中的alpha向量
CvSVM::get_alpha_vector()
7)获取偏移量
CvSVM::get_rho
——结论——
▪决策函数为【rho-w*x】,大于0表示正样本,小于0表示负样本
其中w=alpha*sv;
alpha中存放每个支持向量的权重,sv表示每个支持向量
w为加权后的支持向量
相关文章推荐
- opencv svm使用时遇到的问题
- <Opencv for Android 调试>加载XML模型,使用SVM.predict出现的NullPointerException问题
- opencv knn,svm,ann,人脸识别类的使用总结
- 在 Android Studio 中使用OpenCV所遇到问题
- 关于使用opencv的提速(二)(多线程问题,openMP)
- 使用PCI-E USB3.0扩展板卡解决OPENCV不能同时打开同品牌摄像头的问题
- opencv svm的使用
- 关于Opencv3在使用霍夫变换(houghlines)时一直出问题的解决
- Android开发使用OpenCv中JavaCameraView预览图左旋90度问题
- 使用mingw5.3.0编译opencv2.4.10出现的问题 opencv_java.dir failed
- Android studio使用OpenCV代码问题:No implementation found for long org.opencv.core.Mat.n_Mat()
- Python使用libsvm的“ImportError: No module named svmutil”问题
- 《FAQ:OpenCV Haartraining》——使用OpenCV训练Haar like+Adaboost分类器的常见问题
- OpenCV--使用SVM
- Anaconda使用问题:OpenCV包的配置
- OpenCV中gpu下使用cascade classifier遇到问题的解决方案
- 利用SVM支持向量机对彩色图像进行分割并使用OpenCV进行实现
- Arm下使用Qt和Opencv进行图像处理的入门例程和遇到的问题
- 使用openCV对JPEG图像内存进行解码及时间过长问题;
- Opencv 2.4.6 +VS2010 MFC + StaticLib使用问题