サポートベクターマシンのカーネルによる違いで境界線がどのように変化するかを見てみるよ。
scikit-learn公式ドキュメントの「plot different SVM classifiers in iris dataset」のやつだね。
前回、サポートベクターマシンについて勉強をして、最終的にカーネルを変更することで、境界線を直線(線形)にしたり、曲線にしたりできるというところまでやりました。今回は、scikit-learnの公式ドキュメント、「Plot different SVM classifiers in iris dataset」を参考に、カーネルの違いで境界線を引いてみたいと思います。
公式scikit-learnの公式ドキュメントはこちらからどうぞ
こんな人の役に立つかも
・機械学習プログラミングを勉強している人
・サポートベクターマシンのカーネルによる境界線の違いを知りたい人
境界線を描くプログラムで確認しよう
今回は、アヤメデータを利用するのですが、アヤメデータは4特徴量のため、2特徴量だけに絞ります。
scikit-learn公式ドキュメントのプログラムは若干直感的ではなかったので、分解して作成しなおしました。それぞれのプログラムパート毎に記事を書いていますので、よろしければ参考にしてください。
アヤメデータを2次元化する部分については、こちらの記事で詳細にプログラムを開設していますので、アヤメデータの2次元化がわからない方はご参考ください。
import~2次元アヤメデータの読み込み
ライブラリのimport~アヤメデータを読み込み、2次元のアヤメデータに変換します。
#サポートベクターマシン
from sklearn import svm
from sklearn.datasets import load_iris
#matplotlib
import matplotlib.pyplot as plt
import numpy as np
#import matplotlib.pyplot as plt
panda_box = load_iris()
X = panda_box.data
y = panda_box.target
X_2dim = panda_box.data[:,:2]
次に、境界線を視覚的にわかりやすく描くための関数を作成します。
こちらの記事でも詳しく詳細を記載しておりますので、ご参考ください。
#関数を作成
def make_meshgrid(x, y, h=.02):
x_min, x_max = x.min() - 1, x.max() + 1
y_min, y_max = y.min() - 1, y.max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
return xx, yy
def plot_contours(ax, clf, xx, yy, **params):
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
out = ax.contourf(xx, yy, Z, **params)
return out
def graf_setting(ax):
#ax.set_xticks(())
#ax.set_yticks(())
ax.set_xlabel('Sepal length')
ax.set_ylabel('Sepal width')
サポートベクターマシンに訓練をさせて、境界線を表示します。
以下のプログラムでは、
1.線形サポートベクターマシン
2.リニアカーネルのサポートベクターマシン
3.RBFカーネルのサポートベクターマシン
4.polynominalカーネルのサポートベクターマシン
のそれぞれを試すことができるようになっています。
試したいサポートベクターマシンのコメントアウト(#)を外して、(それ以外はコメントアウトする)利用することで、4種類の境界線を確認することができます。初期は1.線形サポートベクターマシンとなっています。
#===サポートベクターマシンの作成===
C = 1.0
#↓試したいmodelのコメントを外します。
#1.線形サポートベクターマシン
model = svm.LinearSVC()
#2.リニアカーネル
#model = svm.SVC(kernel='linear', C=C)
#3.rbfカーネル
#model = svm.SVC(kernel='rbf', gamma=0.7, C=C)
#4.polynominalカーネル
#model = svm.SVC(kernel='poly', degree=3, gamma='auto', C=C)
#訓練
clf = model.fit(X_2dim, y)
#空のグラフを作成
fig = plt.figure(figsize=(9, 4))
ax = fig.add_subplot(121)
#fig = plt.figure()
#ax = fig.add_subplot(111)
#グリッドのデータを作成
X0, X1 = X[:, 0], X[:, 1]
xx, yy = make_meshgrid(X0, X1)
#グラフに境界線とデータをプロット
plot_contours(ax, clf, xx, yy, cmap=plt.cm.coolwarm, alpha=0.8)
ax.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=20, edgecolors='k')
graf_setting(ax)
線形サポートベクターマシンの境界線は以下のようになりました。
リニアカーネルのSVCは以下のようになりました。線形サポートベクターマシンとリニアカーネルのサポートベクターマシンは、多クラス問題の時に、「ovr」で評価するのか、「ovo」で評価するのかの違いで、境界線の判定に差が出る模様です。
次に、RBFカーネルとpolynominalカーネルを確認してみます。
サポートベクターマシンの使いどころ
以下の通り、scikit-learnの公式ドキュメントによると、まずは線形サポートベクターマシン(LinearSVC)について検討を行うと良いとのことです。
そして、次に検討するのが、k最近傍法、最後にカーネルを使ったサポートベクターマシンということでしょうか。
カーネルを利用するのは最後の手段ということでよさそうです。
線形以外は、いまいち使いどころがわからないから、チューニングの過程で正解率が改善されるような組み合わせを試して利用する、という感じだと思います。