4

libsvm の RBF カーネルを使用して学習したい単純な xor 問題があります。次のような XOR 問題を使用して Java libsvm をトレーニングすると:

XY
0,0 -1
0,1 1
1,0 1
1,1 -1

テスト ベクトル (0,0) を分類した結果は、svm.svm_predict を使用すると -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

私は同じ問題を抱えていたので、XORの問題についてChih-Jen Linに尋ねました。

回答からの引用:

  • -b 1 の場合、内部で 5 倍の cv を実行する必要があります。非常に少数のインスタンスを考えると、奇妙な結果が生じる可能性があります

つまり、多くの同一の入力に対して機能します。入力ベクトルを 5 ~ 6 回コピーして貼り付け、4 ではなく 20 のエントリを作成すると機能します。

また、データが十分に大きい場合にのみ、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 に答える