scikit-learn (sklearn) は Python パッケージの一つで、様々な機械学習アルゴリズムが実装されている。scikit-learn を利用すると、関数一つで特定の機械学習アルゴリズムを呼び出して、学習や予測が行えるようになる。SVM は、scikit-learn の sklearn.svm モジュールで定義されている。このページは、SVM で判別器の作り方を示す。
ここでサンプルデータセットとして scikit-learn パッケージに実装されている乳がんに関するデータセットを使用する。このデータセットには 569 サンプルを含み、30 個の特徴量を持つ。モデルを構築するにあたって、569 サンプルのうち 60% を学習用に使用し、40% を検証用に使用する。なお、学習データと検証データの振り分けについて、再現性を持たせるように random_state=1234
を指定しておく。
簡単な SVM モデルの作り方
まず、ソフトマージン法 SVM のハイパーパラメーター C を 0.1 に固定して、モデルを作成してみる。
import sklearn.datasets
import sklearn.model_selection
import sklearn.metrics
import sklearn.svm
cancer = sklearn.datasets.load_breast_cancer()
X = cancer.data
y = cancer.target
X_train, X_test, y_train, y_test =\
sklearn.model_selection.train_test_split(X, y, test_size=0.4, random_state=1234)
clf = sklearn.svm.SVC(kernel='rbf', C=0.1)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
score = sklearn.metrics.accuracy_score(y_test, y_pred)
print(score)
# 0.7105263157894737
次に、ハイパーパラメーター C の値を 1.0 に固定して、上と同様なコードでモデルを作成してみる。C の値が大きくなると予測精度が上がることがわかる。
import sklearn.datasets
import sklearn.model_selection
import sklearn.metrics
import sklearn.svm
cancer = sklearn.datasets.load_breast_cancer()
X = cancer.data
y = cancer.target
X_train, X_test, y_train, y_test =\
sklearn.model_selection.train_test_split(X, y, test_size=1.0, random_state=1234)
clf = sklearn.svm.SVC(kernel='rbf', C=0.1)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
score = sklearn.metrics.accuracy_score(y_test, y_pred)
print(score)
# 0.8947368421052632
交差検証
次に、もう少し真面目にモデルを構築してみる。まず特徴量を標準化してから主成分分析を行い、データ全体の 60% を説明できるまでの上位にある主成分を使って SVM 判別器を構築する。データについて、学習データをさらにサブセットに分けて 5-fold 交差検証を行うことにする。
import numpy as np
import pandas as pd
import sklearn.model_selection
import sklearn.metrics
import sklearn.preprocessing
import sklearn.decomposition
import sklearn.pipeline
X_train, X_test, y_train, y_test =\
sklearn.model_selection.train_test_split(X, y, test_size=0.4, random_state=1234)
# 5-fold cross-validation
k = 5
skf = sklearn.model_selection.StratifiedKFold(n_splits=k, random_state=1234, shuffle=True)
c_values = [0.01, 0.1, 1.0, 10, 100]
scoring = ['f1_macro', 'precision_macro', 'recall_macro']
scores = None
for c in c_values:
pipe = sklearn.pipeline.Pipeline([
('scaler', sklearn.preprocessing.StandardScaler()),
('pca', sklearn.decomposition.PCA(0.6)),
('clf', sklearn.svm.SVC(kernel='rbf', C=c))
])
score = sklearn.model_selection.cross_validate(pipe, X_train, y_train, scoring=scoring, cv=skf)
x = pd.concat([pd.Series(np.full(k, c), name='C'), pd.DataFrame(score)], axis=1)
scores = pd.concat([scores, x])
print(scores)
## C fit_time ... test_precision_macro test_recall_macro
## 0 0.01 0.004720 ... 0.311594 0.500000
## 1 0.01 0.003941 ... 0.316176 0.500000
## 2 0.01 0.003821 ... 0.316176 0.500000
## :
## :
## 3 100.00 0.003433 ... 0.988372 0.980769
## 4 100.00 0.003202 ... 0.950768 0.956960
次に交差検証で決めた最適な C を使って、モデルを構築する。この際に、学習データのすべてを使ってモデルを構築する(5-fold 交差検証に分けていたサブセットを考慮しない)。次に、構築したモデルを、テストデータでテストする。
best_c = scores.loc[scores.loc[:, 'test_f1_macro'] == max(scores.loc[:, 'test_f1_macro']), 'C'].values[0]
print(best_c)
## 100.0
pipe = sklearn.pipeline.Pipeline([
('scaler', sklearn.preprocessing.StandardScaler()),
('pca', sklearn.decomposition.PCA(0.6)),
('clf', sklearn.svm.SVC(kernel='rbf', C=best_c))
])
pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)
score = sklearn.metrics.accuracy_score(y_test, y_pred)
print(score)
## 0.9035087719298246