强攻了一周,总算放弃了。
Python调LibSVM的话,直接用scikit-learn
包就好了。现在问题是,C和C++怎么来调用。
不用写代码的方法
LibSVM很良心地给了个Demo,就是那个预测心脏大小的例子。源文件在svm-train.c
,直接编译出来就能用。
这样的话就要遵守这个程序的输入格式(具体可参考heart_scale这个文件):
首先,每一行分为两个部分:标签和特征。
标签就是类别啦,例子中是+1和-1。其实用什么都行的。而且标签可以不连续。
然后是特征。需要按照index:value
的形式给出。并且,如果缺失几个标签也是无所谓的,只要连index
一起缺失就好了。
之后运行编译好的svm_train
文件即可开始训练。参数啊什么的也可以运行时指定。
写代码的方法
如果想集成进自己的C/C++代码,也不难。
把svm.h
和svm.c
一起放进项目中,并在自己文件里面引用svm.h
。
首先来构造我们的数据对象:svm_problem
。这个对象又三部分构成:l
是「有多少数据」、x
是「特征矩阵」,y
是对应的标签。其中,x
的类型是svm_mode
,里面也分为两部分,index
和value
。
约定是这样的:例如我有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, ¶m);
最后,训练完毕,要保存一下呀
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;
}
好了,大致就这么多。
发表回复