サポートベクターマシン(SVM)

SVMの概要

サポートベクターマシン(SVM)は、分類と回帰の両方に使用される、強力でありながら柔軟な教師あり機械学習アルゴリズムです。しかし、一般的に、それらは分類問題で使用されます。1960年代に、SVMが最初に導入されましたが、その後1990年に改良されました。SVMには、他の機械学習アルゴリズムと比較して、独自の実装方法があります。最近、複数の連続変数とカテゴリ変数を処理できるため、非常に人気があります。

SVMの動作

SVMモデルは、基本的に、多次元空間の超平面内のさまざまなクラスの表現です。超平面はSVMによって反復的に生成されるため、エラーを最小限に抑えることができます。SVMの目標は、データセットをクラスに分割して、最大限界超平面(MMH)を見つけることです。

以下はSVMの重要な概念です-

  • Support Vectors−超平面に最も近いデータポイントはサポートベクターと呼ばれます。分離線は、これらのデータポイントを使用して定義されます。

  • Hyperplane −上の図からわかるように、これは、異なるクラスを持つオブジェクトのセット間で分割される決定平面または空間です。

  • Margin−異なるクラスのクローゼットデータポイント上の2本の線の間のギャップとして定義できます。これは、ラインからサポートベクターまでの垂直距離として計算できます。大きなマージンは良いマージンと見なされ、小さなマージンは悪いマージンと見なされます。

SVMの主な目標は、データセットをクラスに分割して最大限界超平面(MMH)を見つけることであり、次の2つの手順で実行できます。

  • まず、SVMは、クラスを最良の方法で分離する超平面を繰り返し生成します。

  • 次に、クラスを正しく分離する超平面を選択します。

PythonでのSVMの実装

PythonでSVMを実装するために、次のように標準ライブラリのインポートから始めます。

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns; sns.set()

次に、SVM-を使用して分類するために、sklearn.dataset.sample_generatorから線形分離可能なデータを持つサンプルデータセットを作成しています。

from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples=100, centers=2, random_state=0, cluster_std=0.50)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer');

以下は、100個のサンプルと2個のクラスターを持つサンプルデータセットを生成した後の出力です。

SVMが識別分類をサポートしていることはわかっています。2次元の場合は線を、複数次元の場合は多様体を見つけるだけで、クラスを互いに分割します。上記のデータセットに次のように実装されています-

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
plt.plot([0.6], [2.1], 'x', color='black', markeredgewidth=4, markersize=12)
for m, b in [(1, 0.65), (0.5, 1.6), (-0.2, 2.9)]:
   plt.plot(xfit, m * xfit + b, '-k')
plt.xlim(-1, 3.5);

出力は次のとおりです-

上記の出力から、上記のサンプルを完全に区別する3つの異なるセパレーターがあることがわかります。

説明したように、SVMの主な目標は、データセットをクラスに分割して最大限界超平面(MMH)を見つけることです。したがって、クラス間にゼロ線を描画するのではなく、各線の周りに最も近い点までの幅のマージンを描画できます。それは次のように行うことができます-

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
   for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
   yfit = m * xfit + b
   plt.plot(xfit, yfit, '-k')
   plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none',
         color='#AAAAAA', alpha=0.4)
plt.xlim(-1, 3.5);

上記の出力画像から、識別分類器内の「マージン」を簡単に観察できます。SVMは、マージンを最大化するラインを選択します。

次に、Scikit-Learnのサポートベクター分類器を使用して、このデータでSVMモデルをトレーニングします。ここでは、線形カーネルを使用してSVMを次のように適合させています-

from sklearn.svm import SVC # "Support vector classifier"
model = SVC(kernel='linear', C=1E10)
model.fit(X, y)

出力は次のとおりです-

SVC(C=10000000000.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
kernel='linear', max_iter=-1, probability=False, random_state=None,
shrinking=True, tol=0.001, verbose=False)

ここで、理解を深めるために、以下に2DSVCの決定関数をプロットします。

def decision_function(model, ax=None, plot_support=True):
   if ax is None:
      ax = plt.gca()
   xlim = ax.get_xlim()
   ylim = ax.get_ylim()

モデルを評価するには、次のようにグリッドを作成する必要があります-

x = np.linspace(xlim[0], xlim[1], 30)
y = np.linspace(ylim[0], ylim[1], 30)
Y, X = np.meshgrid(y, x)
xy = np.vstack([X.ravel(), Y.ravel()]).T
P = model.decision_function(xy).reshape(X.shape)

次に、決定境界とマージンを次のようにプロットする必要があります-

ax.contour(X, Y, P, colors='k',
   levels=[-1, 0, 1], alpha=0.5,
   linestyles=['--', '-', '--'])

ここで、同様にサポートベクターを次のようにプロットします-

if plot_support:
   ax.scatter(model.support_vectors_[:, 0],
      model.support_vectors_[:, 1],
      s=300, linewidth=1, facecolors='none');
ax.set_xlim(xlim)
ax.set_ylim(ylim)

ここで、この関数を使用して、次のようにモデルを適合させます。

plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
decision_function(model);

上記の出力から、SVM分類器がマージンを使用してデータに適合していることがわかります。つまり、破線とサポートベクター、この適合の重要な要素が破線に接触しています。これらのサポートベクターポイントは、次のように分類器のsupport_vectors_属性に格納されます。

model.support_vectors_

出力は次のとおりです-

array([[0.5323772 , 3.31338909],
   [2.11114739, 3.57660449],
   [1.46870582, 1.86947425]])

SVMカーネル

実際には、SVMアルゴリズムは、入力データ空間を必要な形式に変換するカーネルを使用して実装されます。SVMは、カーネルトリックと呼ばれる手法を使用します。この手法では、カーネルが低次元の入力空間を取得し、それを高次元の空間に変換します。簡単に言うと、カーネルは、次元を追加することで、分離不可能な問題を分離可能な問題に変換します。これにより、SVMがより強力で、柔軟性があり、正確になります。以下は、SVMで使用されるカーネルの種類の一部です。

線形カーネル

これは、任意の2つの観測間の内積として使用できます。線形カーネルの式は次のとおりです-

k(x、x i)= sum(x * x i

上記の式から、2つのベクトル間の積は&が入力値の各ペアの乗算の合計であると言うことがわかります。

多項式カーネル

これは線形カーネルのより一般化された形式であり、湾曲した入力空間と非線形の入力空間を区別します。以下は、多項式カーネルの式です。

K(x、xi)= 1 + sum(x * xi)^ d

ここで、dは多項式の次数であり、学習アルゴリズムで手動で指定する必要があります。

動径基底関数(RBF)カーネル

主にSVM分類で使用されるRBFカーネルは、入力空間を不定次元空間にマッピングします。次の式はそれを数学的に説明します-

K(x、xi)= exp(-gamma * sum((x – xi ^ 2))

ここで、ガンマの範囲は0〜1です。学習アルゴリズムで手動で指定する必要があります。ガンマの適切なデフォルト値は0.1です。

線形分離可能データ用にSVMを実装したので、線形分離不可能なデータ用にPythonで実装できます。カーネルを使用して実行できます。

以下は、カーネルを使用してSVM分類器を作成する例です。scikit-learnのアイリスデータセットを使用します-

以下のパッケージをインポートすることから始めます-

import pandas as pd
import numpy as np
from sklearn import svm, datasets
import matplotlib.pyplot as plt

ここで、入力データをロードする必要があります-

iris = datasets.load_iris()

このデータセットから、最初の2つの機能を次のように取得しています-

X = iris.data[:, :2]
y = iris.target

次に、SVM境界を元のデータで次のようにプロットします-

x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
   np.arange(y_min, y_max, h))
X_plot = np.c_[xx.ravel(), yy.ravel()]

ここで、正則化パラメーターの値を次のように指定する必要があります。

C = 1.0

次に、SVM分類器オブジェクトを次のように作成できます。

Svc_classifier = svm.SVC(kernel = 'linear'、C = C).fit(X、y)

Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with linear kernel')

出力

Text(0.5, 1.0, 'Support Vector Classifier with linear kernel')

でSVM分類器を作成する場合 rbf カーネル、カーネルをに変更できます rbf 次のように-

Svc_classifier = svm.SVC(kernel='rbf', gamma =‘auto’,C=C).fit(X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with rbf kernel')

出力

Text(0.5, 1.0, 'Support Vector Classifier with rbf kernel')

ガンマの値を「auto」に設定しますが、0から1の間の値を指定することもできます。

SVM分類器の長所と短所

SVM分類器の長所

SVM分類器は、優れた精度を提供し、高次元空間でうまく機能します。SVM分類器は基本的にトレーニングポイントのサブセットを使用するため、結果として使用するメモリは非常に少なくなります。

SVM分類器の短所

トレーニング時間が長いため、実際には大規模なデータセットには適していません。もう1つの欠点は、SVM分類器が重複するクラスではうまく機能しないことです。