LIBSVMを使ってデータ予測してみた

集合知プログラミングの9章を流し読みしました。

サポートベクターマシン
サポートベクターマシンとはTrueとFalseのデータを学習させてテストデータのT or Fを予測する分類器のひとつ。予測精度が良いらしい。
分割線や分割面の予測をするから基本的にはTかFの2種のデータ分類しかすることができず、もっとデータの種類が多い場合は工夫しないといけないみたい。
顔の表情判断とかタンパク質の構造予測とか手書き文字認識とかに使われてるらしいです。へー。

実際にやってみないとわからないのでなんかやってみる。
本当は遺伝子とそうじゃないところの塩基配列のパターンから遺伝子予測とかしてみたかったけど、とりあえず使い方学んでから後で。

pythonのLIBSVMってのがpythonでサポートベクターマシンをできる有名なモジュールっぽいのでこれをインストールする。
一応環境言っておくとOSX 10.8.2でPythonが2.7.3です。
LIBSVM
ここからzipなりをダウンロードして展開。
展開したフォルダでターミナルを開いてmake。
cd pythonしてもう一度makeすれば完了。
これをpythonがimportを呼び出した時に参照されるフォルダであるpythonpathに移動すればいいはずなのでpathを確認する。
pythonの対話型インタプリタで

import sys
for i in sys.path:
      i

とするとpythonpathが確認できる。
どうやら/Library/Python/2.7/site-packagesってところに置けばいいようなのでここにさっきのフォルダを移動する。
これで動くか対話型インタプリタでインポートしてみる。

>>> import svm
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named svm

よくわからないけど上手く通ってないみたいなので直接追加してしまいましょう。
ターミナルを開いて

PYTHONPATH="/Library/Python/2.7/site-packages/libsvm-3.16/python"
export PYTHONPATH

これでpythonpathが通ったはずなので

>>> import svm
>>> import svmutil

ちゃんとインポートできてれば完了。

 

というわけで、ランダムに生成された点の座標が関数で定義された範囲内であるかどうか学習させてみました。
スクリーンショット 2013-02-03 3.39.36
ちょっと見づらいですけどy>sin(x)とy<(x^2)-x-1の共通範囲(図だと濃い青の部分)に位置するデータをT、それ以外をFとしました。
それにしてもこのアプリ使い方がいまいちわからない…
macにデフォルトでついてるグラフ描画アプリで割りと使えそうな気がするんですけどね…

対話型インタプリタで以下を打ち込む

import random, math
from svmutil import *

def func1(x,y):
    fy = math.sin(x)
    if fy < y:
        return 1
    else: return 0

def func2(x,y):
    fy = x**2-x-1
    if fy > y:
        return 1
    else: return 0

#関数1と2が重なってるところは真
def judge(x,y):
    f1 = func1(x,y)
    f2 = func2(x,y)
    if f1 and f2:
        return 1
    else: return 0

#座標クラス
class svmdata:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.judge = judge(x,y)

#点をランダムに100個生成
cordinate = [( (random.random()-0.5)*20, (random.random()-0.5)*20 ) for x in xrange(100)]
datas = [svmdata(x,y) for x,y in cordinate]

#学習データの登録
#第一引数がデータラベル(今回は0か1)
#第二引数がデータ
prob = svm_problem([data.judge for data in datas], [[data.x, data.y]for data in datas])

#パラメーター設定
#引数じゃなく文字列としてパラメーター指定させるの珍しい気がする
param = svm_parameter("-t 0")

#学習させる
t = svm_train(prob, param)

#予測させる
#第一引数がデータ作成者が予測したラベル
#第二引数がデータセットで、リストで渡す
#第三引数が学習させたsvm分類器
p_labels, p_acc, p_vals  = svm_predict( [1,1,1], [ [10,10], [0,0], [-10, -10] ], t)

Accuracy = 33.3333% (1/3) (classification)と表示されれば完了。
データ作成者が予測したラベルと分類器が予測したラベルは1/3が一致してたみたい。
p_labelsを見てみると
[1.0, 0.0, 0.0]
となっている。
予測データは(10,10)が真、(0,0)が偽、(-10,-10)が偽なので正しく分類できてるっぽい。
おわり

*参考*
学習のさせ方とか
[Python] python から SVM を使うときのメモ [SVM]

学習パラメーターとか
PythonでLIBSVMを使う

広告


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中