Feb 22 2014

libsvm の memo

参考; http://www.okuma.nuee.nagoya-u.ac.jp/~sakaguti/wiki/index.php?LibSVM

テストデータ形式

// test.js
for (var i=0; i<100; ++i) {
  var a = [];
  for (var j=0; j<10; ++j) {
    a[j] = Math.round(Math.random());
  }
  var t = a.reduce(function(x,y){return x+y});
  t = t > 5 ? 1 : -1;
  console.log("%d %s"
           , t
           , a.map(function(x, i){return i+':'+x}).join(' '));
}

間違ってた。番号を0スタートにしてるけど、 よく見るとWARNINGが出てて、1スタートにしてほしかったらしい。 ちゃんと動いてるっぽいからまぁいっか

分割公差検証

-t 0 : 線形
-v 10 : 10分割
do:
    svm-train -t 0 -v 10 train.scale

train.scale: test.js
    node test.js > train
    svm-scale train > train.scale

-t で設定した kernel type によって出力が2つあるみたいだけど、

(前略)
*.*
optimization finished, #iter = 102
nu = 0.112336
obj = -5.000000, rho = 0.999823
nSV = 38, nBSV = 1
Total nSV = 38
Cross Validation Accuracy = 100%

入力を倍

for (var i=0; i<100; ++i) {
  var a = [];
  for (var j=0; j<20; ++j) {
    a[j] = Math.round(Math.random());
  }
  var t = a.reduce(function(x,y){return x+y});
  t = t > 10 ? 1 : -1;
  console.log("%d %s"
           , t
           , a.map(function(x, i){return i+':'+x}).join(' '));
}
$ svm-train -t 0 -v 10 train.scale

(前略)
..........*......................*
optimization finished, #iter = 2885
nu = 0.094086
obj = -4.186700, rho = 0.285305
nSV = 19, nBSV = 0
Total nSV = 19
Cross Validation Accuracy = 99%

パリティ (xor)

for (var i=0; i<100; ++i) {
  var a = [];
  for (var j=0; j<10; ++j) {
    a[j] = Math.round(Math.random());
  }
  var t = a.reduce(function(x,y){return x+y});
  t = t % 2 ? 1 : -1;
  console.log("%d %s"
           , t
           , a.map(function(x, i){return i+':'+x}).join(' '));
}

線形

$ svm-train -t 0 -v 10 train.scale

(前略)
.........*
optimization finished, #iter = 860
nu = 0.669745
obj = -59.094108, rho = 0.338879
nSV = 65, nBSV = 53
Total nSV = 65
Cross Validation Accuracy = 61%

多項式

$ svm-train -t 1 -v 10 train.scale

(前略)
.*
optimization finished, #iter = 139
nu = 0.710394
obj = -43.537098, rho = 0.154695
nSV = 81, nBSV = 40
Total nSV = 81
Cross Validation Accuracy = 41%

RBF

$ svm-train -t 1 -v 10 train.scale

(前略)
*.*
optimization finished, #iter = 104
nu = 0.778061
obj = -51.085066, rho = 0.243366
nSV = 86, nBSV = 52
Total nSV = 86
Cross Validation Accuracy = 59%

50%は下回らないで欲しかった。

簡単なパリティ

for (var i=0; i<100; ++i) {
  var a = [];
  for (var j=0; j<10; ++j) {
    a[j] = Math.round(Math.random());
  }
  var t = a.slice(0,2).reduce(function(x,y){return x+y});
  t = t % 2 ? 1 : -1;
  console.log("%d %s"
           , t
           , a.map(function(x, i){return i+':'+x}).join(' '));
}

入力は10だけど初めの2つだけで答えは実は決まってる。

-t 0 1 2
Ac. 52% 62% 82%

パラメタのいじり方はわかってないので -t-v 10 以外のオプション以外はつけてない。

入力を倍

for (var i=0; i<100; ++i) {
  var a = [];
  for (var j=0; j<20; ++j) {
    a[j] = Math.round(Math.random());
  }
  var t = a.slice(0,2).reduce(function(x,y){return x+y});
  t = t % 2 ? 1 : -1;
  console.log("%d %s"
           , t
           , a.map(function(x, i){return i+':'+x}).join(' '));
}

入力の数は倍だけど、やはり最初の2つだけで答えは決まる。

-t 0 1 2
Ac. 49% 45% 70%

期待してたような数字は出なかったのだけど、 あとSVMは入力次元がどんなに大きくてもうまい事取捨してくれるとか聞いた気がするんだけど、 けどけど、 パラメタのイジリ方勉強しないとだ。

分かった

はじめの方に書いたように (今気付いて追記した) 1スタートにして、 それとテストデータの数を10倍にしたら上手く行った。 入力次元20に対してテストデータ100件ってのは多くなかったみたい。

for (var i=0; i<1000; ++i) {
  var a = [];
  for (var j=0; j<20; ++j) {
    a[j] = Math.round(Math.random());
  }
  var t = a.slice(0,2).reduce(function(x,y){return x+y});
  t = t % 2 ? 1 : -1;
  console.log("%d %s"
           , t
           , a.map(function(x, i){return (i+1)+':'+x}).join(' '));
}
$ svm-train -t 2 -v 10 train.scale

(前略)
..*.*
optimization finished, #iter = 3026
nu = 0.597604
obj = -276.353274, rho = -0.007254
nSV = 823, nBSV = 199
Total nSV = 823
Cross Validation Accuracy = 100%