利用LIBSVM估计概率

来源:互联网 发布:马鞍山百助网络待遇 编辑:程序博客网 时间:2024/04/30 13:48

前言

在研究分类问题时,可能会遇到需要分类器返回样本属于每一类的概率,而不是直接输出该样本的类别的情况。因为之前一直使用opencv库进行开发,所以也想在opencv的ml模块寻找是否有对应功能的SVM分类器,无果。最后发现最新的LIBSVM库提供类似功能的函数。于是,借助LIBSVM,实现了样本的概率估计。过程如下:

过程

  1. 下载最新的LIBSVM,官网http://www.csie.ntu.edu.tw/~cjlin/libsvm/。使用之前,建议阅读README。
  2. 打开cmd,进入libsvm -> windows。
  3. 训练之前,建议采用svm-train进行归一化。语法如下:svm-scale -l lower -u upper data_filename > scale_data_filename
    示例如下:
svm-scale -l -1 -u 1 -s range train > train.scale

这里需要注意svm_type,kernel_type,probability_estimates这几个参数。为了得到概率模型,需要将probability_estimates置1。例子如下:

svm-train -s 0 -b 1 data_file

注:为了方便,可将上述过程保存为一个批处理文件。
4. 训练完成后,得到model文件。然后在cpp文件中调用。主要分为载入模型,构造节点,调用概率估计函数。代码如下:

    svm_node* charac = new svm_node[featureNum+1];    if (joint.cols != featureNum)    {        cout << "single joint characters calculate error" << endl;        return -1;    }    //特征向量归一化    //normalize(joint, joint, 0, 1, NORM_MINMAX, -1);    for (int i = 0; i < joint.rows; i++)    {        float* rowData = joint.ptr<float>(i);        for (int j = 0; j < joint.cols; j++)        {            charac[j].index = j + 1;            charac[j].value = rowData[j];        }    }    charac[featureNum].index = -1;    //prob_estimates是否需要预分配空间,待调试    //经调试,需要预分配空间    //调试发现,只要模型固定,无论charac是多少,输出的概率固定    double* prob_estimates = new double[labelNum];    int* label = new int[labelNum];    //svm_get_labels(svmModel[classffierIndex], label);    label = svmModel[classffierIndex]->label;    if (svm_check_probability_model(svmModel[classffierIndex]) == 1)        svm_predict_probability(svmModel[classffierIndex], charac, prob_estimates);    double pj = prob_estimates[label[id]];    delete[] charac;    delete[] prob_estimates;    return pj;

注:注意模型中的类别顺序和训练时的类别顺序的差异性,如果相同则不需要改,否则需要按照模型的类别顺序来输出概率。

总结

在调试过程中,发现SVM概率模型的准确率比直接输出类别的模型的准确率低。就我自己的样本而言,前者的准确率为70%左右,而后者的准确率为100%。目前还不清楚原因。

0 0
原创粉丝点击