OpenCV 3.0中的SVM训练 参数解析

opencv3.0和2.4的SVM接口有不同,基本可以按照以下的格式来执行:

ml::SVM::Params params;
params.svmType = ml::SVM::C_SVC;
params.kernelType = ml::SVM::POLY;
params.gamma = 3;
Ptr svm = ml::SVM::create(params);
Mat trainData; // 每行为一个样本
Mat labels;    
svm->train( trainData , ml::ROW_SAMPLE , labels );
// ...

svm->save("....");//文件形式为xml,可以保存在txt或者xml文件中
Ptr svm=statModel::load("....");

Mat query; // 输入, 1个通道
Mat res;   // 输出
svm->predict(query, res);

 但是要注意,如果报错的话最好去看opencv3.0的文档,里面有函数原型和解释,我在实际操作的过程中,也做了一些改动

   1)设置参数

    SVM的参数有很多,但是与C_SVC和RBF有关的就只有gamma和C,所以设置这两个就好,终止条件设置和默认一样,由经验可得(其实是查阅了很多的资料,把gamma设置成0.01,这样训练收敛速度会快很多)

Ptr svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->setGamma(0.01);
svm->setC(10.0);
svm->setTermCriteria(TermCriteria(CV_TERMCRIT_EPS, 1000,FLT_EPSILON));

  svm_type –指定SVM的类型,下面是可能的取值:

  CvSVM::C_SVC C类支持向量分类机。 n类分组 (n \geq 2),允许用异常值惩罚因子C进行不完全分类。
  CvSVM::NU_SVC \nu类支持向量分类机。n类似然不完全分类的分类器。参数为 \nu 取代C(其值在区间【0,1】中,nu越大,决策边界越平滑)。
  CvSVM::ONE_CLASS 单分类器,所有的训练数据提取自同一个类里,然后SVM建立了一个分界线以分割该类在特征空间中所占区域和其它类在特征空间中所占区域。
  CvSVM::EPS_SVR \epsilon类支持向量回归机。训练集中的特征向量和拟合出来的超平面的距离需要小于p。异常值惩罚因子C被采用。
  CvSVM::NU_SVR \nu类支持向量回归机。 \nu 代替了 p。

  kernel_type –SVM的内核类型,下面是可能的取值:

  CvSVM::LINEAR 线性内核。没有任何向映射至高维空间,线性区分(或回归)在原始特征空间中被完成,这是最快的选择。K(x_i, x_j) = x_i^T x_j.
  CvSVM::POLY 多项式内核: K(x_i, x_j) = (\gamma x_i^T x_j + coef0)^{degree}, \gamma > 0.
  CvSVM::RBF 基于径向的函数,对于大多数情况都是一个较好的选择: K(x_i, x_j) = e^{-\gamma ||x_i - x_j||^2}, \gamma > 0.
  CvSVM::SIGMOID Sigmoid函数内核:K(x_i, x_j) = \tanh(\gamma x_i^T x_j + coef0).

  degree – 内核函数(POLY)的参数degree。

  gamma – 内核函数(POLY/ RBF/ SIGMOID)的参数\gamma。

  coef0 – 内核函数(POLY/ SIGMOID)的参数coef0。

  Cvalue – SVM类型(C_SVC/ EPS_SVR/ NU_SVR)的参数C。

  nu – SVM类型(NU_SVC/ ONE_CLASS/ NU_SVR)的参数 \nu。

  p – SVM类型(EPS_SVR)的参数 \epsilon。

  class_weights – C_SVC中的可选权重,赋给指定的类,乘以C以后变成 class\_weights_i * C。所以这些权重影响不同类别的错误分类惩罚项。权重越大,某一类别的误分类数据的惩罚项就越大。

  term_crit – SVM的迭代训练过程的中止条件,解决部分受约束二次最优问题。您可以指定的公差和/或最大迭代次数。

2)训练

Mat trainData;
Mat labels;
trainData = read_mnist_image(trainImage);
labels = read_mnist_label(trainLabel);

svm->train(trainData, ROW_SAMPLE, labels); 

3)保存

svm->save("mnist_dataset/mnist_svm.xml");

3. 测试,比对结果

 (此处的FLT_EPSILON是一个极小的数,1.0 - FLT_EPSILON != 1.0)

Mat testData;
Mat tLabel;
testData = read_mnist_image(testImage);
tLabel = read_mnist_label(testLabel);

float count = 0;
for (int i = 0; i < testData.rows; i++) {
    Mat sample = testData.row(i);
    float res = svm1->predict(sample);
    res = std::abs(res - tLabel.atint>(i, 0)) <= FLT_EPSILON ? 1.f : 0.f;
    count += res;
}
cout << "正确的识别个数 count = " << count << endl;
cout << "错误率为..." << (10000 - count + 0.0) / 10000 * 100.0 << "%....\n";

这里没有使用svm->predict(query, res);

然后就查看了opencv的文档,当传入数据是Mat 而不是cvMat时,可以利用predict的返回值(float)来判断预测是否正确。

你可能感兴趣的:(svm)