4

我有一个简单的异或问题,我想在 libsvm 中使用 RBF 内核来学习。当我使用 XOR 问题训练 java libsvm 时,例如:

xy
0,0 -1
0,1 1
1,0 1
1,1 -1

如果我使用 svm.svm_predict,我对测试向量 (0,0) 进行分类得到的结果为 -1,但如果我使用 svm.svm_predict_probability,则为 +1。甚至返回的概率也是相反的。我使用的代码和结果如下。谁能告诉我我在这里做错了什么?

public static void main(String[] args) {
    svm_problem sp = new svm_problem();
    svm_node[][] x = new svm_node[4][2];
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 2; j++) {
            x[i][j] = new svm_node();
        }
    }
    x[0][0].value = 0;
    x[0][1].value = 0;

    x[1][0].value = 1;
    x[1][1].value = 1;

    x[2][0].value = 0;
    x[2][1].value = 1;

    x[3][0].value = 1;
    x[3][1].value = 0;


    double[] labels = new double[]{-1,-1,1,1};
    sp.x = x;
    sp.y = labels;
    sp.l = 4;
    svm_parameter prm = new svm_parameter();
    prm.svm_type = svm_parameter.C_SVC;
    prm.kernel_type = svm_parameter.RBF;
    prm.C = 1000;
    prm.eps = 0.0000001;
    prm.gamma = 10;
    prm.probability = 1;
    prm.cache_size=1024;
    System.out.println("Param Check " + svm.svm_check_parameter(sp, prm));
    svm_model model = svm.svm_train(sp, prm);
    System.out.println(" PA "+ model.probA[0] );
    System.out.println(" PB " + model.probB[0] );
    System.out.println(model.sv_coef[0][0]);
    System.out.println(model.sv_coef[0][1]);
    System.out.println(model.sv_coef[0][2]);
    System.out.println(model.sv_coef[0][3]);
    System.out.println(model.SV[0][0].value + "\t" + model.SV[0][1].value);
    System.out.println(model.SV[1][0].value + "\t" + model.SV[1][1].value);
    System.out.println(model.SV[2][0].value + "\t" + model.SV[2][1].value);
    System.out.println(model.SV[3][0].value + "\t" + model.SV[3][1].value);
    System.out.println(model.label[0]);
    System.out.println(model.label[1]);
    svm_node[] test = new svm_node[]{new svm_node(), new svm_node()};
    test[0].value = 0;
    test[1].value = 0;
    double[] l = new double[2]; 
    double result_prob = svm.svm_predict_probability(model, test,l);
    double result_normal = svm.svm_predict(model, test);
    System.out.println("Result with prob " + result_prob);
    System.out.println("Result normal " + result_normal);
    System.out.println("Probability " + l[0] + "\t" + l[1]);
}

- - - - - 结果 - - - - - - -

Param Check null
*
.
.
optimization finished, #iter = 3
nu = 0.0010000908050150552
obj = -2.000181612091545, rho = 0.0
nSV = 4, nBSV = 0
Total nSV = 4
 PA 3.2950351477129125
 PB -2.970957107176531E-12
1.0000908039844314
1.0000908060456788
-1.0000908039844314
-1.0000908060456788
0.0 0.0
1.0 1.0
0.0 1.0
1.0 0.0
-1
1
Result with prob 1.0
Result normal -1.0
Probability 0.03571492727188865     0.9642850727281113

显然结果是完全相反的。这似乎发生在我选择作为测试的任何示例中。

有人可以对此有所了解吗?提前致谢

4

5 回答 5

3

我问过林志仁关于异或的问题,因为我有同样的问题

来自答案的引用:

  • 对于 -b 1,在内部我们需要做一个 5 倍的 cv。鉴于如此少的情况,可能会出现奇怪的结果

这意味着,对于许多相同的输入,它可以工作。复制/粘贴输入向量 5-6 次,以获得 20 个条目而不是 4 个条目,它会起作用。

这也意味着 svm_predict 将始终为您提供正确的答案,仅当数据足够大时 svm_predict_probability 。不要忘记,两种方法的输出并不相同

于 2012-11-23T14:25:16.767 回答
2

据我所知,概率输出向量的顺序和libsvm在训练数据中遇到类的顺序是一样的。确保您首先拥有所有类别 0(例如带有标签 1)的示例,然后是类别 1(例如带有标签 -1)的所有示例,这将使输出按照您可能期望的方式进行。这在使用 matlab 界面进行培训时对我有用,但对于 c 和 java 版本应该同样有效。

于 2011-10-16T15:07:29.427 回答
1

这只是一半的答案,因为我也无法让它工作......

我认为您指定的数据不正确。libsvm 使用稀疏数据格式,这意味着每个 svm_node 都有一个索引和一个位置。这是一种效率度量,允许您省略对于具有很少非零特征的大向量为零的特征。

所以,你的代码应该是:

x[0][0].index = 1;
x[0][0].value = 0;      
x[0][1].index = 2;
x[0][1].value = 0;
x[1][0].index = 1;
x[1][0].value = 1;
x[1][1].index = 2;
x[1][1].value = 1;
x[2][0].index = 1;
x[2][0].value = 0;      
x[2][1].index = 2;
x[2][1].value = 1;
x[3][0].index = 1;
x[3][0].value = 1;      
x[3][1].index = 2;
x[3][1].value = 0;

test[0].index = 1;
test[0].value = 0;
test[1].index = 2;
test[1].value = 0;

但这似乎并不能解决问题。希望这是朝着正确方向迈出的一步。

于 2011-05-18T08:54:57.650 回答
0

我不知道 libsvm,但是从其他库来看,您可能会简单地误解概率输出的含义——它可能不是属于“正”类的概率,而是属于第一个输入样本的类的概率,在您的情况下其标签为-1。因此,如果您对样本重新排序,使第一个样本的标签为 +1,您可能会得到预期的输出。

于 2011-05-16T13:00:44.753 回答
0

您的最后一个索引在训练和测试数据中应该是 -1。

于 2013-05-29T02:03:35.427 回答