LibSVM C++ 版本用法

强攻了一周,总算放弃了。

Python 调 LibSVM 的话,直接用 scikit-learn 包就好了。现在问题是,C 和 C++怎么来调用。

不用写代码的方法

LibSVM 很良心地给了个 Demo,就是那个预测心脏大小的例子。源文件在 svm-train.c,直接编译出来就能用。

这样的话就要遵守这个程序的输入格式(具体可参考 heart_scale 这个文件):

首先,每一行分为两个部分:标签和特征。

标签就是类别啦,例子中是+1 和-1。其实用什么都行的。而且标签可以不连续。

然后是特征。需要按照 index:value 的形式给出。并且,如果缺失几个标签也是无所谓的,只要连 index 一起缺失就好了。

之后运行编译好的 svm_train 文件即可开始训练。参数啊什么的也可以运行时指定。

写代码的方法

如果想集成进自己的 C/C++代码,也不难。

svm.hsvm.c 一起放进项目中,并在自己文件里面引用 svm.h

首先来构造我们的数据对象:svm_problem。这个对象又三部分构成:l 是「有多少数据」、x 是「特征矩阵」,y 是对应的标签。其中,x 的类型是 svm_mode,里面也分为两部分,indexvalue

约定是这样的:例如我有 10 个样本,每个样本经过 OpenCV 特征提取后,均可得到 32 维特征向量。所以我们的代码可以这样来写:

auto feature = feature_extract(...);

svm_problem problem;
problem.l = 10;
problem.x = new svm_node*[10];
problem.y = new double[10];
for (int i=0; i<10; ++i){
    problem.x[i] = new svm_node[32+1];
    for(int j=0; j<32; ++j){
        problem.x[i][j].index = j + 1;
        problem.x[i][j].value = feature.at<float>(i,j);
    }
    problem.x[i][32] = -1;
    problem.y[i] = label[i];
}

其中要点是,index 从 1 开始,最后补个-1。

如何训练 svm,写它的训练参数。例如下面这段代码:

svm_parameter param{C_SVC, RBF, 3, 0.1, 0, 20, 1e-3, 1, 0, nullptr, nullptr, 0.5, 0.1, 0, 0};

具体含义可以看头文件。

然后愉快地开始训练吧:

auto model = svm_train(&problem, &param);

最后,训练完毕,要保存一下呀

if (svm_save_model(output_file.c_str(), model)) {
    std::cerr << "Save SVM to [" << output_file << "] FAILED" << std::endl;
} else {
    std::cout << "Save SVM to [" << output_file << "] SUCCEED." << std::endl;
}

好了,大致就这么多。

留下评论