scikit-learnでsvm 基本的な使い方
今更だがsvmを使いたかったのでscikit-learnで使い方を調べた。
公式ドキュメントが整っているのでそっち見ただけでもわかる。
1.4. Support Vector Machines — scikit-learn 0.19.2 documentation
以下参考
Scikit-learnでハイパーパラメータのグリッドサーチ
scikit-learnによる多クラスSVM
2013.07.15 はじパタlt scikit-learnで始める機械学習
とりあえず使う
とりあえず使うというだけなら何も考えず
from sklearn import svm clf = svm.SVC() clf.fit(train_features, train_labels)
とすれば識別器の学習ができる。
その後テストデータに対して推定を行うには
test_pred = clf.predict(test_features)
でおけ。
変数test_pred
には推定ラベルが羅列したnumpy.ndarray
が入る。
これを真値と比較して結果を見るには、
from sklearn.metrics import classification_report, accuracy_score print classification_report(test_labels, test_pred) print accuracy_score(test_labels, test_pred)
とすれば、結果をF値と認識率で評価してくれる。
F値については以下参照
F値 - 機械学習の「朱鷺の杜Wiki」
いやそんなの興味ねーから、Confusion matrixくださいよって時は
from sklearn.metrics import confusion_matrix print confusion_matrix(test_labels, test_pred)
で表示できる。F値とかは何か結果がごまかされてる感があるけど
Confusion matrix見せとけばとりあえず誰でも納得する、ような気がする
カーネルなどのパラメータを指定する場合は
clf = svm.SVC(kernel='rbf', C=1, gamma=0.1)
のように指定する。
デフォルトではRBFカーネルで、C=1.0, gamma= 1/特徴数 となっている。
チューニングする
svmの性能を引き出すには各種パラメータを調整する必要がある
まずカーネルだが、上で述べたようにsvm.SVC
はデフォルトではRBFカーネルを使う
基本的にはRBF、特徴の次元数が大きい時は線形カーネルでもいいらしい
RBFカーネルでは調整するパラメータはと、線形はだけ
これをグリッドサーチで探索する
(詳しいことは勉強中・・・こことかわかりやすいのかも)
なんとscikit-learnでは一行でグリッドサーチする関数が用意されている。
parameters = [{'kernel':('rbf'), 'C':numpy.logspace(-4, 4, 9), 'gamma':numpy.logspace(-4, 4, 9)}, {'kearnel':('rbf'), 'C':numpy.logspace(-4, 4, 9)} ] clf = grid_search.GridSearchCV(svm.SVC(), parameters, n_jobs = -1) clf.fit(train_features, train_labels) print clf.best_estimator_
parameters
で指定したパラメータでグリッドサーチを行う。
n_jobs
でCPUのコア数を指定して並列計算してくれる。(-1で自動決定)
ただしその分使用するメモリ量も大きくなる。当たり前だけど。
特徴量の次元が大きい場合、メモリが足りなくなってエラーになることがあるので注意。
print clf.best_estimator_
でベストパラメータを表示できる。
ここでGridSearchCV
にcv
という引数を整数で指定すると、
指定したfold数でCross-validationをやってくれる。もういたれりつくせりである。
結果はclf.grid_scores_
に入っているので下みたいに表示できる。
print"mean score for cross-validation:\n" for params, mean_score, all_scores in clf.grid_scores_: print "{:.3f} (+/- {:.3f}) for {}".format(mean_score, all_scores.std() / 2, params)
clf.grid_scores_
には
params
(cross-validationのパラメータ),
mean_score
(cross_validation後の平均認識率),
all_score
(各foldでの認識率)が格納されている。
ついでにall_score.std()
で標準偏差を求めて を表示するようにしてる。
format関数って便利だね
結果はこんな感じ↓
mean score for cross-validation: 0.782 (+/- 0.004) for {'kernel': 'rbf', 'C': 0.0001, 'gamma': 0.0001} 0.854 (+/- 0.002) for {'kernel': 'rbf', 'C': 0.0001, 'gamma': 0.001} 0.786 (+/- 0.006) for {'kernel': 'rbf', 'C': 0.0001, 'gamma': 0.01} 0.798 (+/- 0.003) for {'kernel': 'rbf', 'C': 0.0001, 'gamma': 0.1} ...
パラメータによってはすごい数になる。
詳しくはドキュメント参照。
sklearn.grid_search.GridSearchCV — scikit-learn 0.19.2 documentation
テストデータの推定は上と同じようにできる。
One-versus-Rest か One-versus-One か
多クラス分類を行う場合、一つの特徴量がどのクラスに分類されるかを決定するのに2つの方法がある。
- ある特定のクラスに入るか、それ以外に入るか(One-versus-Rest、以後ovr)
- ある特定のクラスに入るか、別のある特定のクラスに入るか(One-versus-One、以後ovo)
クラス分類問題を考えた時、
ovrでは個の分類器を利用し、
ovoでは個の分類器を利用する、という違いがある。
svm.SVC
はdecision_function_shape
という引数でこれらを指定できる。
デフォルトでは'ovo'となっているが、'ovr'のほうが推奨されている(識別性能が良い?)
2016/2/20の時点ではバージョン1.7.0が最新だが、1.8ではデフォルトを'ovr'にすると公式で宣言されてるから
結構性能が違ってくるのかもしれない。
感想
アホでも使えるレベルにしてくれていて助かる。
あとは理論的なことを勉強せねば・・・