@qiezhian
2014-11-15T08:38:30.000000Z
字数 3681
阅读 6199
research
转自:http://www.itnose.net/detail/6095711.html。
当然对于一个特定的SVM训练器,里面的所有参数不一定全用。比如我用的svm_type为EPS_SVR,那么我要用到的参数主要就是p,c,gama这三个参数。下面是设置参数的代码
新窗口打开复制代码
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);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可以自动选择最优值,但在代码中也要先赋初始值,要不然编译能通过,但运行时会报错。下面是示例代码
新窗口打开复制代码
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设为0CvParamGrid 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 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设为0CvParamGrid 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);