MySVM に関する Tips

[戻る]

ちょっとサポートベクターマシンというのに興味が沸いてきました. サポートベクターマシンって何かというと パターン x があるクラスに属するか属さないかを 知るためのアルゴリズムのようで

  1. あらかじめ学習用サンプル x1, x2, x3... xn を 用意しておきそれぞれクラス A に属するか属さないかを y1, y2, y3,...yn に 1, -1 で入れておく.
  2. すると f(x)=Σαi yi, K(x, xi) + b という式をかませばf の正負によって新しいパターン x がクラス A に属するか属さないかが判別できる.
というものらしい.

ここで K(x, x') はカーネルと呼ばれるものでいろんなやり方が ありまた学習時に αi がどういう数値なのかめんどうくさい計算で求めなくては いけない. このへんがややこしいとともにサポートベクターマシンの味噌らしいのだが まぁ良くわからないのでパスします. 詳しく知りたい人は電子情報通信学会 6/2000, 「津田宏治/サポートベクターマシンとは何か」という解説記事から 入ってみるのがいいでしょう (ちなみに上の式はこの文献の式 8 です).

んで本題ですが何かいいサンプルは無いかと WEB をさまよってみると ここ にライブラリがいろいろ 転がっていて WinSVMなる ものがありました. 早速 GET して使ってみたのですがやっぱりよく分かりません.

試行錯誤の結果

  1. 学習用サンプルを作る (以下のファイルを hoge.txt という名前で保存)
    @parameters
    
    #training set
    @examples
    format xy
    7 0 7
    9 1 10
    4 6 11
    3 8 11
    9 4 13
    5 6 11
    5 4 9
    6 0 6
    7 4 11
    4 5 9
    
  2. WinSVM を起動し「Input file」に 1 で作ったファイルを指定し [Learn] ボタンを押す
  3. するとhoge-svm.txt というファイルができるので今度はそれを 開いて最後の方に以下のような問題を追加する.
    @examples
    format xy
    2 2 0
    3 6 0
    4 8 0
    4 5 0
    3 5 0
    5 6 0
    7 4 0
    6 0 0
    
  4. 今度は「Input file」で 3 のファイルを指定し「Predict」ボタンを押す.
  5. すると hoge-svm-pred.txt というファイルが出来ているので中を覗くと 以下のようになっている
    # examples ys
    4.00015
    9.00018
    12.0002
    9.00013
    8.00016
    11.0001
    11
    6.00001
    
とすればいいのかなと思いました. 2 における問題はたんなる足し算で最初の二つの数意を足したのが三番目の数です. 3 の問題の回答が 5 だとすると一応それなりの答えです. 実際WinSVM のページではこういう結果を例にあげ「悪くないでしょ」 と書いてますが正直疑問が残ります.

というのはサポートベクターマシンというのは正負によるクラス判別なので デジタル的な結果を期待しているのにこのアナログ的な結果は意味不明です.

そこで WinSVM のベースとなっている MySVM を調べてみることにしました. MySVM は make 一発の UNIX 系なんですがVC++.NET でブレークポイントを張りながら変数をウォッチするという軟弱な解析方法を 行うためソースとプロジェクトをちょっと改造しました. 具体的には

  1. MySVM というディレクトリを掘りその下に lib というディレクトリを掘り learn.cpp, predict.cpp, Makefile 以外の全ファイルを置く.
  2. MySVM の下に learn というコンソールアプリプロジェクトを作る.
  3. MySVM/learn の下に learn.cpp というファイルが出来るので オリジナルの learn.cpp で上書き.
  4. learn.cpp を開きダブルコーテーションで括ってある include 文に "../lib/" という文字列を追加.
  5. プロジェクトに ../lib 配下の全ファイルを追加する
  6. ビルドしてエラーが無くなるまで を繰り返す.
  7. predict に関しても同じことをする.
といったことを行いました.

ちなみに使い方は WinSVM にて [Input file] ボタンを押す代わりに 引数でファイルを指定します.

さて実際にプログラムを追ってみると上述した式は svm_c::predict() 内で計算されているようです. ただしx に対して妙な計算を事前になされています. 何なんでしょう.

ここで上述したアナログ的な数値は 識別面からの距離ではないかと考えました. 要は人間に理解しやすいよう感覚に合わせてスケーリングしなおしている... (本当かどうかは知りません. 単にそう思っただけです) この推測が正しいかどうか分かりませんがno_scale というオプションがあることに気づきためしに上記 1 の段階で

@parameters
no_scale

#training set
@examples
format xy
7 0 -1
9 1 -1
4 6 -1
3 8 1
9 4 1
5 6 1
5 4 -1
6 0 -1
7 4 1
4 5 -1
と no_scale を加えた後9 以上が 1, 9 未満が -1 と正負でクラス分けし かつ3 の段階で頭に
@parameters
no_scale
を加えてみます.

するとどうでしょう. 一応結果はそれらしく正負で 9 以上/未満を判別しているようです. no_scale を加えたものでsvm_c::predict() における変数を見てみると 内部で例の式そのままを計算しているようでやっと理解できるようになりました. もっとも yi に関しては学習時に αi × yi として計算し 3 で出来るファイルの第 4 パラメータに入れているようです. はい.

なおくどいですがここに書いたことが必ずしも本当かどうかは知りません. 単に私がそう考えただけです. (私には見つけられなかったですが) もしかしてマニュアルのどこかに書いてあるのかもしれませんし...

っとここまで解読できたところで こちらの方に 別のライブラリを発見しました. ライセンスも LGPL だし ソースも見た感じ分かりやすいし (実はまだコンパイルすらしてないんですが) こっちに乗り換えようかと思っています.


2005.9