fc2ブログ

LIBSVM java版を使う

2012年02月20日 02:44

LIBSVM java版を使う

kinectを使ったアプリケーションで、決まった動きを検出するための一つの方法としてSVMを使う事を考えた。
現在は、OpenNI + java で kinect を使っているので、java言語で使えるsvmライブラリを探した。

以下が割と有名なようだったので使ってみた。

LIBSVM -- A Library for Support Vector Machines
http://www.csie.ntu.edu.tw/~cjlin/libsvm/


このページで、java実装は二つ紹介されている
・LIBSVMのjava実装(C++のコードをそのままjavaに変換した感じ)
 ・http://www.csie.ntu.edu.tw/~cjlin/libsvm/#download
・jlibsvm: LIBSVMをパフォーマンス、拡張性の観点からリファクタリングしたコード
 ・http://dev.davidsoergel.com/trac/jlibsvm/

このふたつのうち、説明だけ読むとjlibsvmの方がよく見えるが、実際使ってみると未実装部分が大杉だったので、上のLIBSVMのjava実装を使った。

・使い方

1.モデルの作成

1-1.元ネタファイルの作成

以下のような形式の元ネタファイルを作る


1 1:-0.0013786764705882354 2:0.0057157628676470585 3:4.5955882352941165E-4 4:0.00112655739379085 5:38.0 6:-83.0 7:236.0
1 1:-4.468958652830196E-4 2:0.001708883828216933 3:-0.0029316591163263133 4:-0.0029494415206854367 5:49.0 6:21.0 7:900.0
2 1:-8.053472566307697E-4 2:0.015825596141435506 3:6.725430580246377E-4 4:0.019385799543923065 5:196.0 6:-40.0 7:506.0
2 1:-1.7673336983657553E-4 2:0.021002586194578676 3:0.005701880761361455 4:0.00407827378102308 5:216.0 6:34.0 7:399.0
3 1:-8.170953867899441E-4 2:-0.0023765650581102004 3:0.0016513781990655056 4:0.011545796818632416 5:169.0 6:-149.0 7:1603.0
3 1:-0.011345886334911794 2:-0.004779992024791061 3:0.010344040288070138 4:0.015262516965389552 5:38.0 6:-84.0 7:700.0
4 1:-8.15206561207011E-4 2:-0.012176408105470035 3:-5.230214125755292E-4 4:0.014526629528803993 5:196.0 6:-118.0 7:533.0
4 1:-0.005219037617901608 2:-0.010753445963518873 3:0.005010016891373788 4:0.011383035605288017 5:100.0 6:-71.0 7:567.0
...



形式は

クラス名 パラメータ番号:値 パラメータ番号:値 パラメータ番号:値 ...

である必要がある。


1-2.svm_trainの実行


元ネタを例えばinput.txtという名前で保存した場合、

java svm_train -t 0 input.txt



を実行すると、input.txt.model というファイルが作成される。
なお、 -t でカーネル関数を選ぶ事ができる。0にすると線形カーネル,2にするとガウシアンカーネルになる。
(デフォルトはガウシアンカーネル)その他のパラメータなど詳しくは→http://www.csie.ntu.edu.tw/~cjlin/libsvm/

1-2.モデルの検証


モデルの検証を行うコマンドがある。とくに別途検証データがないので、入力データを食わせてみる。

java svm_predict input.txt input.txt.model output.txt



このコマンドの結果は以下のように出力される。

Accuracy = 70.1219512195122% (115/164) (classification)



Accuracyは、input.txtのデータ行に書かれたクラス名と生成されたモデルで判別されたクラス名が正しかった割合である。

(元ネタデータを使っているのに100%でないのは、モデルを作るときに外れ値が捨てられたのだろう、と今の所解釈している。)

output.txtは以下のように出力されている。

1.0
1.0
2.0
2.0
...


これは、モデルを使って判別された行ごとに出力されている。

2.判別


javaコードの中で、モデルのロード、判別対象にしたいデータの作成、判別を実行する。


// モデルのロード
svm_model model = svm.svm_load_model("input.txt.model");
...
// 判別対象にしたいデータ
svm_node[] input = new svm_node[7];
input[0] = new svm_node();
...
// ラベルをセット
input[0].index = 1;
input[1].index = 2;
...
// 値をセット
input[0].value = "ラベル1のデータ";
input[1].value = "ラベル2のデータ";
...
//判別の実行
double v = svm.svm_predict(model,input);



の様に実行する。

以上。

・感想


ツールとしては、簡単に使える。

しかし当然ながら入力データとして何を選ぶかが重要。現在あまり認識率をあげられてないので、別の入力データを選ぼうと考えている。

あと、ガウシアンカーネルで、gammaをデフォルトで使うと元ネタデータを再度svm_predictした際にAccuracy 100%となるモデルができたが、このモデルを実際に使って別の入力データを判別させるとある一つのクラスにしか分別しない分別器になってしまった。gammaの値を小さくするとこの現象はなくなった。この辺り、現在カーネル関数やカーネルパラメータの選定よりもまず入力データを再考する事が有効と考えて、まだあまり深追いはしていない。
スポンサーサイト





コメント

    コメントの投稿

    (コメント編集・削除に必要)
    (管理者にだけ表示を許可する)

    トラックバック

    この記事のトラックバックURL
    http://aaatxt.blog57.fc2.com/tb.php/77-e016d72b
    この記事へのトラックバック