唯物是真 @Scaled_Wurm

プログラミング(主にPython2.7)とか機械学習とか

LIBSVMとかLIBLINEARとかのメモ

LIBSVM -- A Library for Support Vector MachinesとかLIBLINEAR -- A Library for Large Linear Classificationを使って二値分類の問題で遊んでいました。
その時にすぐにわからなかったことのメモ。

Accuracy以外の尺度を出力する

普通LIBSVMやLIBLINEARを使ってクロスバリデーションをするとAccuracyが出力されますが、二値分類においてはその他の尺度PrecisionやRecall、F値やAUCなどが見たい時があります。

こちらの記事ではLIBSVMでPrecisionやRecall、F値を出力させるパッチが公開されています。
簡単に適用できてわかりやすいです。

こちらはPrecision、Recallに加えてAUCやBACも出力させることができるらしいです。
手順が多少めんどくさいです。
以下拙訳

  1. eval.cpp, eval.h, Makefileをダウンロードして LIBSVMのディレクトリに入れる (Makefileは上書きする)
  2. svm-train.c と svm-predict.c に #include "eval.h" という記述を加える
  3. svm-train.c の main 関数にある do_cross_validation(); という文を以下の文に置き換える
    • double cv = binary_class_cross_validation(&prob, &param, nr_fold);
    • printf("Cross Validation = %g%%\n",100.0*cv);
  4. svm-predict.c の main 関数にある predict(input,output); という文を以下の文に置き換える
    • binary_class_predict(input, output);
  5. eval.cpp にある以下のグローバル変数に出力させたい評価尺度の関数(auc, precision, recall, fscore, bac)を指定する。
    • double (*validation_function)(const dvec_t&, const ivec_t&) = auc;
  6. 新しい Makefile で再コンパイルする
    • make clean; make
http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/eval/index.html

LIBLINEARについて同様の出力をさせたい場合も同じページに手順が書いてあります。

識別結果の確率を出力する

以下の確率を出力させる方法は上で紹介した、RecallやPrecisionなどの尺度を出力させるパッチを当てているとなぜか出力されなかったので注意。

LIBSVM

「確率を出力するといえばロジスティック回帰で、そういう用途にはSVMは使えない」と思っていましたが、LIBSVMでも識別結果の確率を出力できるようです
具体的には学習時と予測時に -b 1 を指定すればよいらしいです。

svm-train -b 1 train.dat
svm-predict -b 1 test.dat train.dat.model output

以上のようなコマンドを実行すると、出力ファイルoutputに推定されたラベルだけでなくそれぞれの確率が出力されています。

LIBLINEAR

LIBLINEARではロジスティック回帰を使った(-s 0 を指定)場合のみ確率値を出力することができます。
またpredictで予測するときには -b 1 を指定する必要があります。

train -s 0 train.dat
predict -b 1 test.dat train.dat.model output

grid.pyをLIBLINEARで使う

LIBSVMにはパラメータのグリッドサーチ用のスクリプトgrid.pyがついています(LIBSVMのtoolsディレクトリ内)。
これは以下のように使います

python grid.py -log2c 最初の値,最後の値,ステップ幅 -log2g 最初の値,最後の値,ステップ幅 svm-trainに対するパラメータ train.dat

-log2c はパラメータCについての探索する値の範囲とステップ幅を表しています。
これは2のn乗の形になっていて、-log2c -1,1,1 の場合はCを(0.5, 1, 2)の3つについて試すということを表しています
同様に-log2g はパラメータgammaについての範囲を表しています。

これはLIBLINEARに対しても使うことができます。
具体的には -log2g に null を指定し、 -svmtrain にLIBLINEARの train を指定します。
LIBLINEARの train がカレントディレクトリにあるとすると、以下のようなコマンドになります。

python grid.py -log2c -5,5,1 -log2g null -svmtrain ./train train.dat

パラメータやカーネルの選択、素性のスケーリングなど

過去の記事でも言及しましたが以下のブログ記事がわかりやすいです。