SVM (Support Vector Machine)

SVM 소개

SVM (Support Vector Machine)은 분류 및 회귀 모두에 사용되는 강력하면서도 유연한 감독 형 기계 학습 알고리즘입니다. 그러나 일반적으로 분류 문제에 사용됩니다. 1960 년대에 SVM이 처음 도입되었지만 나중에 1990 년에 개선되었습니다. SVM은 다른 기계 학습 알고리즘에 비해 고유 한 구현 방식을 가지고 있습니다. 최근에는 여러 연속 형 및 범주 형 변수를 처리 할 수 ​​있기 때문에 매우 인기가 있습니다.

SVM의 작동

SVM 모델은 기본적으로 다차원 공간의 초평면에있는 서로 다른 클래스의 표현입니다. 하이퍼 플레인은 오류를 최소화 할 수 있도록 SVM에 의해 반복적 인 방식으로 생성됩니다. SVM의 목표는 최대 한계 초평면 (MMH)을 찾기 위해 데이터 세트를 클래스로 나누는 것입니다.

다음은 SVM에서 중요한 개념입니다-

  • Support Vectors− 초평면에 가장 가까운 데이터 포인트를 지원 벡터라고합니다. 이러한 데이터 포인트의 도움으로 구분선이 정의됩니다.

  • Hyperplane − 위의 다이어그램에서 볼 수 있듯이, 이것은 서로 다른 클래스를 가진 객체 세트로 나누어 진 결정 평면 또는 공간입니다.

  • Margin− 서로 다른 클래스의 옷장 데이터 포인트에서 두 줄 사이의 간격으로 정의 할 수 있습니다. 선에서지지 벡터까지의 수직 거리로 계산할 수 있습니다. 큰 마진은 좋은 마진으로 간주되고 작은 마진은 나쁜 마진으로 간주됩니다.

SVM의 주요 목표는 최대 한계 하이퍼 플레인 (MMH)을 찾기 위해 데이터 세트를 클래스로 나누는 것이며 다음 두 단계로 수행 할 수 있습니다.

  • 첫째, 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);

출력은 다음과 같습니다.

위의 출력에서 ​​위의 샘플을 완벽하게 구별하는 세 가지 구분 기호가 있음을 알 수 있습니다.

논의 된 바와 같이, SVM의 주요 목표는 데이터 세트를 클래스로 분할하여 최대 한계 하이퍼 플레인 (MMH)을 찾는 것이므로 클래스 사이에 0 선을 그리는 대신 각 선 주위에 가장 가까운 지점까지 약간의 여백을 그릴 수 있습니다. 다음과 같이 할 수 있습니다-

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)

이제 더 나은 이해를 위해 다음은 2D SVC에 대한 결정 함수를 플로팅합니다.

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에서 사용하는 커널 유형 중 일부입니다.

선형 커널

두 관측치 사이의 내적 (dot product)으로 사용할 수 있습니다. 선형 커널의 공식은 다음과 같습니다.

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

위의 공식에서 두 벡터 사이의 곱은 &가 각 입력 값 쌍의 곱셈의 합이라는 것을 알 수 있습니다.

다항 커널

선형 커널의보다 일반화 된 형태이며 곡선 또는 비선형 입력 공간을 구분합니다. 다음은 다항 커널의 공식입니다.

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

여기서 d는 학습 알고리즘에서 수동으로 지정해야하는 다항식의 정도입니다.

방사형 기저 함수 (RBF) 커널

SVM 분류에 주로 사용되는 RBF 커널은 무한 차원 공간에서 입력 공간을 매핑합니다. 다음 공식은 그것을 수학적으로 설명합니다-

K (x, xi) = exp (-감마 * 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()

이 데이터 세트에서 다음과 같이 처음 두 가지 기능을 사용합니다.

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 분류기의 단점

훈련 시간이 길기 때문에 실제로는 대규모 데이터 세트에 적합하지 않습니다. 또 다른 단점은 SVM 분류 기가 겹치는 클래스에서 제대로 작동하지 않는다는 것입니다.