2020年7月1日水曜日

scikit-learn で SVM を試してみた

概要

過去に Ruby で SVM を試しました
今回は Python の scikit-learn を使って SVM を試してみます
環境は Jupyter notebook 上にプリインストールされている scikit-learn を使います

環境

  • macOS 10.15.5
  • Python 3.8.3
    • scikit-learn 0.22.1 on Jupyter notebook

学習データとテストデータのダウンロード

前回と同じ SVM 用の手書き文字データを使います

  • wget 'https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/pendigits'
  • wget https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/pendigits.t

データの読み込み

SVM のデータフォーマットである libsvm データフォーマットであれば load_svmlight_file というメソッドがそのまま使えます

from sklearn.datasets import load_svmlight_file
index_train, label_train = load_svmlight_file("./pendigits")

こんな感じでラベルとデータの部分に分割してくれます

学習させる

では学習させます
scikit-learn に svm を使います

from sklearn import svm
clf = svm.SVC()
clf.fit(index_train, label_train)

たったこれだけです
svm.SVC で SVM 用のオブジェクトを作成しあとは fit で学習データを与えればこれだけで学習できます
clf は classifier の略で分類器になります
この分類器を使ってテストデータを評価してみます

評価する

テストデータを読み込んでテストしてみましょう

index_test, label_test = load_svmlight_file("./pendigits.t")
clf.predict(index_test)

まずテストデータを評価するとテストデータがどれに分類されたかの結果の配列が返ってきます
配列はテストデータの行分あります
あとはこの結果の配列と label_test の値を比較すれば OK です
正解率を出すのに便利な accuracy_score という関数があるのでこれを使います

result = clf.predict(index_test)
from sklearn.metrics import accuracy_score
accuracy_score(label_test, result)

これで実行すると「0.9817038307604345」という値が得られると思います
前回 Ruby で 0.9824 くらいだったのでほぼ同じ値になりました
今回は SVM のカーネルやガンマ値などのチューニングは行わなかったのでそこの誤差が出た感じだと思います

ちなみにデフォルトは SVC(C=1.0, break_ties=False, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape='ovr', degree=3, gamma='scale', kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False) でした
各パラメータの意味はこちらがわかりやすく解説しています

おまけ: モデルを保存するには

pickle という機能があるのでこれを使えば外部に保存できます

import pickle
s = pickle.dumps(clf)
clf = pickle.loads(s)

再度使う場合は pickle.loads すれば OK です

最後に

Python の scikit-learn を使って SVM を試してみました
データさえあれば SVM の仕組みを知らなくても簡単に分類することができました
コードの行数も Ruby のときに比べてだいぶ少なくて済むのも嬉しい点かなと思います

参考サイト

0 件のコメント:

コメントを投稿