SVMの各カーネルにおける識別結果

イントロ

scikit-learnのサポートベクターマシンを使用できるSVCメソッドを使用する時に指定できるkernel(カーネル)パラメーターがあります。

このkernelパラメーターには、'linear'、'poly'、'rbf'、'sigmoid'を指定することができます。

カーネルを設定できる理由を超簡単に説明すると、サポートベクターマシンが識別を行う時に使用する関数にカーネルを使用することで計算コストを削減して、計算を高速化できる利点があるからです。

そうは言ってもカーネルって4つもあるし、どれを設定すればいいのかわからないと思ったので、本記事ではアヤメのデータセットに対してそれぞれのカーネルを適用した結果を見てみる。

本記事では、上から順に各セルを実行することで、Jupyter notebookで簡単に実装できるようになっています。

sklearnからアヤメデータセットのロード

簡単のためアヤメデータの3、4番目の2次元データを使用します。

# 前処理 データセットのダウンロード

%matplotlib inline

from sklearn import datasets
import numpy as np

# アヤメデータセットを用いる
iris = datasets.load_iris()
# データセットのdict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names', 'filename'])

# 例として、3,4番目の特徴量の2次元データで使用
# iristデータの特徴量['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']の3、4番目を使用
x = iris.data[:, [2,3]]

# クラスラベルを取得
# target_names : ['setosa' 'versicolor' 'virginica']
y = iris.target

データの前処理

次に前処理として、未知データへの汎用性を評価するために、学習データと評価データに分割し、それぞれのデータを標準化する。

# データの前処理

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

#学習データと評価データに分割には、scikit-learnのtrain_test_split()関数を使う。
# 今回は学習データを70%、評価データを30%としている。
# 乱数を制御するパラメータ random_state は None にすると毎回異なるデータを生成する
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=None )

# データの標準化処理 : データの平均値と分散を変換する操作、平均値を0、分散を1とすることが多い
sc = StandardScaler()   # 標準化処理のインスタンスの作成
sc.fit(x_train)    # x_trainの平均と分散を記憶
x_train_std = sc.transform(x_train)
x_test_std = sc.transform(x_test)

カーネルにおけるモデルの学習とそれぞれの正解率の評価

# モデルの学習~精度評価
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
from mlxtend.plotting import plot_decision_regions

kernel_str = ["linear", "poly", "rbf", "sigmoid"]

for k in kernel_str:
    # SVCのインスタンス生成
    model = SVC(kernel = k, random_state=None)
    
    # 識別器の学習
    model.fit(x_train_std, y_train)
    
    # 学習データのクラス分類
    pred_train = model.predict(x_train_std)
    
    # 学習データの予測結果の精度計算
    accuracy_train_score = accuracy_score(y_train, pred_train)
    
    # 評価データのクラス分類
    pred_test = model.predict(x_test_std)
    
    # 評価データの予測結果の精度計算
    accuracy_test_score = accuracy_score(y_test, pred_test)
    
    print(k)
    print("学習データの正解率:%.2f" % accuracy_train_score)
    print("評価データの正解率:%.2f" % accuracy_test_score)

    # データの可視化
    plt.style.use('ggplot')

    # trainデータとtestデータを連結
    x_combined_std = np.vstack((x_train_std, x_test_std))
    y_combined = np.hstack((y_train, y_test))

    fig = plt.figure(figsize=(13, 8))
    plot_decision_regions(x_combined_std, y_combined, clf=model, res=0.02)
    plt.show()

上記のコードを実行すると、以下のように各カーネルでどのように識別されているかを見ることができる。

実行結果

カーネル linear
学習データの正解率:0.97
評価データの正解率:0.93

f:id:Yunos:20200503214408p:plain
図1. linear

カーネル poly
学習データの正解率:0.95
評価データの正解率:0.93

f:id:Yunos:20200503145340p:plain
図2. poly

カーネル rbf
学習データの正解率:0.96
評価データの正解率:0.93

f:id:Yunos:20200503214453p:plain
図3. rbf

カーネル sigmoid
学習データの正解率:0.93
評価データの正解率:0.93

f:id:Yunos:20200503214436p:plain
図4. sigmoid