今回はサポートベクタマシン(分類)の実装をまとめていきます。
※以降、SVMと省略することがあります。
##■ サポートベクタマシンの手順
次の7つのSTEPで進めます。
- モジュールの用意
- データの準備
- データの可視化
- モデルの作成
- モデルのプロット
- 分類を予測
- モデルの評価
##1. モジュールの用意
最初に、必要なモジュールをインポートしておきます。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# データセットを読み込むモジュール
from sklearn.datasets import load_iris
# 標準化(分散正規化)を行うモジュール
from sklearn.preprocessing import StandardScaler
# 訓練データとテストデータを分割するモジュール
from sklearn.model_selection import train_test_split
# サポートベクトルマシンを実行するモジュール
from sklearn.svm import SVC
# 分類の評価を行うモジュール
from sklearn.metrics import classification_report
##2. データの準備
今回はirisデータセットを使って、二値分類をしていきます。
最初にデータの取得をし、標準化を行ってから分割します。
# irisデータセットの読み込み
iris = load_iris()
# 目的変数と説明変数に分ける
X, y = iris.data[:100, [0, 2]], iris.target[:100]
# 標準化(分散正規化)
std = StandardScaler()
X = std.fit_transform(X)
# 訓練データとテストデータに分割する
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
二値分類を行うために、データセットを100行目まで(Setosa・Versicolor のみ)と指定しています。
またプロットしやすくするために、説明変数も2つに絞っています。(Sepal Length・Petal Lengh のみ)
標準化は、例えば2桁と4桁の特徴量(説明変数)があった際に、後者の影響が大きくなってしまうため
全ての特徴量に対して平均を0・分散を1にして、スケールを揃えています。
##3. データの可視化
SVMで分類をする前のデータをプロットして見ておきます。
# 描画オブジェクトとサブプロットの作成
fig, ax = plt.subplots()
# Setosa のプロット
ax.scatter(X_train[y_train == 0, 0], X_train[y_train == 0, 1],
marker = 'o', label = 'Setosa')
# Versicolor のプロット
ax.scatter(X_train[y_train == 1, 0], X_train[y_train == 1, 1],
marker = 'x', label = 'Versicolor')
# 軸ラベルの設定
ax.set_xlabel('Sepal Length')
ax.set_ylabel('Petal Length')
# 凡例の設定
ax.legend(loc = 'best')
plt.show()
Setosa (y_train ==0) に対応する特徴量(0:Sepal Lengh を横軸, 1: Petal Length を縦軸)でプロット
Versicolor (y_train ==1) に対応する特徴量(0:Sepal Lengh を横軸, 1: Petal Length を縦軸)でプロット
<出力結果>
##4. モデルの作成
最初にSVMの実行関数(インスタンス)を作成し、訓練データに当てはめます。
# インスタンスを作成
svc = SVC(kernel = 'linear', C = 1e6)
# 訓練データからモデルを作成
svc.fit(X_train, y_train)
今回はすでに線形分離(1本の直線で分ける)が可能なので、引数を kernel = 'linear' に設定しています。
また C はハイパーパラメータで、出力数値やプロットを見ながら自身で調整していくものです。
##5. モデルのプロット
訓練データからサポートベクタマシンのモデルが作成できたので
どのように分類ができているのか、プロットして確認します。
前半は、先ほどの散布図のコードと全く同じです。
# 描画オブジェクトとサブプロットの作成
fig, ax = plt.subplots()
# Setosa のプロット
ax.scatter(X_train[y_train == 0, 0], X_train[y_train == 0, 1],
marker = 'o', label = 'Setosa')
# Versicolor のプロット
ax.scatter(X_train[y_train == 1, 0], X_train[y_train == 1, 1],
marker = 'x', label = 'Versicolor')
ax.set_xlabel('Sepal Length')
ax.set_ylabel('Petal Length')
ax.legend(loc = 'upper left')
# ここから下は、他データの場合でもそのままペーストして毎回流用できます。(数値の微調整は必要)
# 決定境界(直線)のプロット範囲を指定
xmin = -2.0
xmax = 2.5
ymin = -1.5
ymax = 1.8
# 決定境界とマージンをプロット
xx, yy = np.meshgrid(np.linspace(xmin, xmax, 100), np.linspace(ymin, ymax, 100))
xy = np.vstack([xx.ravel(), yy.ravel()]).T
p = svc.decision_function(xy).reshape(100, 100)
ax.contour(xx, yy, p, colors = 'k', levels = [-1, 0, 1], alpha = 1,
linestyles = ['--', '-', '--'])
# サポートベクタをプロット
ax.scatter(svc.support_vectors_[:, 0], svc.support_vectors_[:, 1],
s = 250, facecolors = 'none', edgecolors = 'black')
plt.show()
alpha:直線の濃さ
s:サポートベクタ(○)の大きさ
<出力結果>
##6. 分類を予測
モデルが完成したので、分類の予測をしていきます。
# 分類結果を予測する
y_pred = svc.predict(X_test)
# 予測値と正解値を出力
print(y_pred)
print(y_test)
<出力結果>
# 予測値と正解値を比較してみる
y_pred: [0 1 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 1 1 1]
y_test: [0 1 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 1 1 1]
0:Setosa 1:Versicolor
今回の場合は全て一致(正解)していることが分かります。
##7. モデルの評価
今回は分類(二値分類)となるので、混同行列を用いた適合率・再現率・F値で評価を行います。
# 適合率、再現率、F値を出力
print(classification_report(y_test, y_pred))
以上より、Setosa と Versicolor における分類の評価を行うことができました。
##■ 最後に
SVMでは上記1~7の手順をもとに、モデルの作成・評価を行っていきます。
今回は初学者の方向けに、実装(コード)のみまとめさせていただきましたが
今後タイミングを見て、理論(数式)についても記事を作成していければと思います。
ご精読いただき、ありがとうございました。
参考文献:Pythonによるあたらしいデータ分析の教科書
(Python 3 エンジニア認定データ分析試験 主教材)