retrofocus’s blog

Compressed Sensingの勉強

SVMの使い方

当たり前のように「SVMで分類しました-」と言えるようになりたい。
そんな人のためにPractical Guide to SVMなんてものがある。
http://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf

日本語の概要はd.hatena.ne.jp

先に日本語のスライドを読んでから原文を当たると素早く理解できる。
今回はおすすめ手順を踏んでSVMを使ってみたい。

使用するのはお馴染みscikit-learn。
データは手書き数字認識を行ってみる。

0.サンプルデータの読み込み

from sklearn import datasets
digits = datasets.load_digits()

data = digits.data
target = digits.target

1. クラスラベルをつける。

元論文では{red, green, blue} を (0,0,1), (0,1,0), (1,0,0)とラベル付けしろと書いてある。
scikit-learnではSVCとNuSVCでは自動でそうしてくれる。よって上記のtargetをそのまま使えばよい。
1.4. Support Vector Machines — scikit-learn 0.16.1 documentation

2. データのスケーリング

特徴量ごとにスケーリングする。今回の場合は特徴量が画素値だが、たとえば、身長と体重なんか違う指標のものを比べたりする場合に単位が違う効果を打ち消す必要がある。
今回は標準化(平均0、標準偏差1)を行う。調べてみるとscikit-learnにあった。
4.3. Preprocessing data — scikit-learn 0.16.1 documentation

from sklearn import preprocessing
scaled = preprocessing.scale(data)

3. カーネルにはRBFを使う。

scikit-learnのSVCはデフォルトでRBFを使うようになっている。呼び出し時に指定すればよい。
(SVCのCはClassificationのCらしい。回帰の場合はRになる)

4. Cross-validationとグリッド探索してパラメータであるCとγを決定する。

これもすでに実装されている。
sklearn.grid_search.GridSearchCV — scikit-learn 0.16.1 documentation

論文では例としてC=[2^-5, ..., 2^15], γ=[2^-15, ..., 2^3]いるのでそれを使ってみる。

from sklearn import svm, grid_search
parameters = {'C':np.logspace(-5, 15, 21, base=2), 'gamma':np.logspace(-15, 3, 19, base=2)}
svc = svm.SVC(kernel='rbf')
gridcv = grid_search.GridSearchCV(svc, parameters, cv=5, verbose=1, n_jobs=4)
gridcv.fit(scaled_data, target)

cvがサンプルを何分割するか、verboseで途中経過の表示をコントロールできる。

可視化ツールはついていないので自分で作成する。

means = np.array([s[1] for s in gridcv.grid_scores_]).reshape(len(c_range), len(g_range))

plt.xscale('log')
plt.yscale('log')
plt.imshow(means, extent=[g_range[0], g_range[-1], c_range[0], c_range[-1]], interpolation='none')
print(gridcv.best_params_)
print(gridcv.best_score_)

f:id:retrofocus:20150502102202p:plain

ちょっとわかりにくいけど、ベスト結果のパラメータ{'C': 32.0, 'gamma': 0.0078125} scoreは0.959となった。絵は真っ赤でわかりにくいけど、一様真ん中あたりにピークがありそうなので、細かい探索をする。
すると、
{'C': 10.947368421052632, 'gamma': 0.0069901315789473685}
0.959376739009

まぁ今回はあまり変わらず。

5.最後に最適化したCとγで学習データ全体を使って学習させる。

c_best = gridcv.best_params_["C"]
g_best = gridcv.best_params_["gamma"]
svc = svm.SVC(kernel='rbf', C=c_best, gamma=g_best)
svc.fit(scaled_data, target)

これでお手軽SVMの完成である。
scikit-learnを使うと楽勝ですね。

サポートベクターマシン入門

サポートベクターマシン入門